david david - 8 days ago 8
Java Question

Best way to iterate two lists and extract few things?

I have two classes as shown below. I need to use these two classes to extract few things.

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
}


Now I have below code where I am iterating above two classes and extracting
schema
given a
clientId
.

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();
}


Is there any better way of getting what I need by iterating those two above classes in couple of lines instead of what I have? I am using Java 7.

Answer

You're doing a linear search operation, which is inneficient. You can do this operation in constant time by first creating (in linear time) a mapping from id->object for each list. This would look something like this:

// do this once, in the constructor or wherever you create these lists
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);
}

Then your lookup simply becomes:

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();
}

In Java 8 you could write it like this:

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