Java 迭代两个列表并提取少量内容的最佳方法?

Java 迭代两个列表并提取少量内容的最佳方法?,java,list,arraylist,Java,List,Arraylist,我有两门课,如下所示。我需要使用这两个类来提取一些东西 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 deviceI

我有两门课,如下所示。我需要使用这两个类来提取一些东西

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的情况下提取模式

有没有更好的方法来获得我所需要的,通过在几行中迭代上面的两个类来代替我所拥有的?我正在使用Java 7。

您正在执行*搜索操作,这是不有效的。您可以在固定时间内完成此操作,首先在线性时间内为每个列表创建一个from id->object。这看起来像这样:

// 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());
}
然后,您的查找就会变成:

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();
}
在Java 8中,您可以这样编写:

// 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());
}
*在实践中,假设客户端ID是唯一的,则您的算法是线性的,但从技术上讲,它仍然在^2上,因为您可能会针对流程列表的每个元素接触proc列表的每个元素。稍微调整一下您的算法,就可以在假设唯一ID的情况下再次保证线性时间:

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();
}
当然,使用“地图”可以确保时间恒定,这要好得多。

您正在执行*搜索操作,这是不够的。您可以在固定时间内完成此操作,首先在线性时间内为每个列表创建一个from id->object。这看起来像这样:

// 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());
}
然后,您的查找就会变成:

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();
}
在Java 8中,您可以这样编写:

// 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());
}
*在实践中,假设客户端ID是唯一的,则您的算法是线性的,但从技术上讲,它仍然在^2上,因为您可能会针对流程列表的每个元素接触proc列表的每个元素。稍微调整一下您的算法,就可以在假设唯一ID的情况下再次保证线性时间:

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

当然,使用地图可以确保时间恒定,这比使用地图要好得多。

我想知道用番石榴能做些什么,不小心写下了这篇文章

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

对不起。

我想知道番石榴能做些什么,不小心写下了这篇乱七八糟的文章

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

抱歉。

您在java7中使用的是可选的?是的,它来自guava而不是Java8。一:您也有流吗?您需要嵌套这两个循环吗?clientId不是唯一的吗?但是我怎样才能得到模式呢?您在java7中使用的是可选的?是的,它来自guava而不是Java8 one:您也有流吗?您需要嵌套2个循环吗?clientId不是唯一的吗?但我如何获得模式呢?您是指ProcessMetadataCyclientID.putprocess.getClientId,process;?您是指ProcessMetadataCyclientId.putprocess.getClientId,process;?我只需要给你一张票,让你勇敢地承认你的所作所为-我只需要给你一张票,让你勇敢地承认你的所作所为-