2016-11-24 14 views
1

私は以下のように2つのクラスを持っています。私はこれらの2つのクラスを使用していくつかのものを抽出する必要があります。2つのリストを繰り返し、いくつかのものを抽出する最良の方法は?

public final class ProcessMetadata { 
    private final String clientId; 
    private final String deviceId; 
    // .. lot of other fields here 

    // getters here 
} 

public final class ProcMetadata { 
    private final String deviceId; 
    private final Schema schema; 
    // .. lot of other fields here 
} 

今、私は二つのクラスの上に反復してclientId与えschemaを抽出していたコードの下に持っています。

public Optional<Schema> getSchema(final String clientId) { 
    for (ProcessMetadata metadata1 : processMetadataList) { 
    if (metadata1.getClientId().equalsIgnoreCase(clientId)) { 
     String deviceId = metadata1.getDeviceId(); 
     for (ProcMetadata metadata2 : procMetadataList) { 
     if (metadata2.getDeviceId().equalsIgnoreCase(deviceId)) { 
      return Optional.of(metadata2.getSchema()); 
     } 
     } 
    } 
    } 
    return Optional.absent(); 
} 

は私が代わりに私が持っているものの行のカップルにそれらの2つの以上のクラスを繰り返すことで必要なものを得るための任意のより良い方法はありますか?私はJava 7を使用しています。

+0

あなたはjava7でオプションを使用していますか? – developer

+1

はいそれはグアバからではなく、Java 8の1つです:) – john

+0

Streamsもありますか? – njzk2

答えて

6

quadratic *の検索操作は不十分です。各リストのid-> objectから(直線時間で)mappingを最初に作成することで、この操作を一定の時間内に行うことができます。これは、次のようになります。

// do this once, in the constructor or wherever you create these lists 
// even better discard the lists and use the mappings everywhere 
Map<String, ProcessMetadata> processMetadataByClientId = new HashMap<>(); 
for (ProcessMetadata process : processMetadataList) { 
    processMetadataByClientId.put(process.getClientId(), process); 
} 

Map<String, ProcMetadata> procMetadataByDeviceId = new HashMap<>(); 
for (ProcMetadata metadata2 : procMetadataList) { 
    procMetadataByDeviceId.put(proc.getDeviceId(), proc); 
} 

次に、あなたの検索が簡単になった:

public Optional<Schema> getSchema(String clientId) { 
return Optional.fromNullable(processMetadataByClientId.get(clientId)) 
    .map(p -> procMetadataByDeviceId.get(p.getDeviceId())) 
    .map(p -> p.getSchema()); 
} 

*実際には:Javaの8で

public Optional<Schema> getSchema(String clientId) { 
    ProcessMetadata process = processMetadataByClientId.get(clientId); 
    if (process != null) { 
    ProcMetadata proc = procMetadataByDeviceId.get(process.getDeviceId()); 
    if (proc != null) { 
     return Optional.of(proc.getSchema()); 
    } 
    } 
    return Optional.absent(); 
} 

あなたはこのようにそれを書くことができますあなたのアルゴリズムはクライアントIDが一意だと仮定すると線形ですが、技術的にはO(n^2)プロセスリストのすべての要素のprocリストのnt。あなたのアルゴリズムに若干の微調整は、(再び固有のIDを仮定して)線形時間をguarenteeことができます。

public Optional<Schema> getSchema(final String clientId) { 
    for (ProcessMetadata metadata1 : processMetadataList) { 
    if (metadata1.getClientId().equalsIgnoreCase(clientId)) { 
     String deviceId = metadata1.getDeviceId(); 
     for (ProcMetadata metadata2 : procMetadataList) { 
     if (metadata2.getDeviceId().equalsIgnoreCase(deviceId)) { 
      return Optional.of(metadata2.getSchema()); 
     } 
     } 
     // adding a break here ensures the search doesn't become quadratic 
     break; 
    } 
    } 
    return Optional.absent(); 
} 

もちろんマップを使用しますがはるかに優れている、一定の時間を保証します。

+0

あなたは 'processMetadataByClientId.put(process.getClientId()、process);'を意味しましたか? –

+0

@KlitosKyriacou固定、ありがとう! – dimo414

1

私はグアバで何ができるのだろうと思って、間違いなくこの熱い混乱を書きました。

import static com.google.common.collect.Iterables.tryFind 

public Optional<Schema> getSchema(final String clientId) { 
    Optional<String> deviceId = findDeviceIdByClientId(clientId); 
    return deviceId.isPresent() ? findSchemaByDeviceId(deviceId.get()) : Optional.absent(); 
} 

public Optional<String> findDeviceIdByClientId(String clientId) { 
    return tryFind(processMetadataList, new ClientIdPredicate(clientId)) 
    .transform(new Function<ProcessMetadata, String>() { 
     String apply(ProcessMetadata processMetadata) { 
     return processMetadata.getDeviceId(); 
     } 
    }); 
} 

public Optional<Schema> findSchemaByDeviceId(String deviceId) { 
    return tryFind(procMetadataList, new DeviceIdPredicate(deviceId.get()) 
    .transform(new Function<ProcMetadata, Schema>() { 
     Schema apply(ProcMetadata procMetadata) { 
     return processMetadata.getSchema(); 
     } 
    }); 
} 

class DeviceIdPredicate implements Predicate<ProcMetadata> { 
    private String deviceId; 

    public DeviceIdPredicate(String deviceId) { 
    this.deviceId = deviceId; 
    } 

    @Override 
    public boolean apply(ProcMetadata metadata2) { 
    return metadata2.getDeviceId().equalsIgnoreCase(deviceId) 
    } 
} 

class ClientIdPredicate implements Predicate<ProcessMetadata> { 
    private String clientId; 

    public ClientIdPredicate(String clientId) { 
    this.clientId = clientId; 
    } 

    @Override 
    public boolean apply(ProcessMetadata metadata1) { 
    return metadata1.getClientId().equalsIgnoreCase(clientId); 
    } 
} 

申し訳ありません。

+0

私はちょうどあなたが何をしたのかを認めるほど勇敢な投票をしなければなりませんでした;-) –

関連する問題