Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/379.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用JavaStreams过滤复杂列表元素-代码优化_Java_Optimization_Java 8_Java Stream - Fatal编程技术网

使用JavaStreams过滤复杂列表元素-代码优化

使用JavaStreams过滤复杂列表元素-代码优化,java,optimization,java-8,java-stream,Java,Optimization,Java 8,Java Stream,我有一个复杂的元素列表。每个内部列表包含3个字段:代码、名称、版本。 我需要得到列表的最终列表,其中有每个代码的最大版本号 下面的代码片段按预期工作,但正在寻找有效的解决方案 List<List<Object>> lists = new ArrayList<>(); List<List<Object>> finalList = new ArrayList<>(); // each list contains => c

我有一个复杂的元素列表。每个内部列表包含3个字段:代码、名称、版本。 我需要得到列表的最终列表,其中有每个代码的最大版本号

下面的代码片段按预期工作,但正在寻找有效的解决方案

List<List<Object>> lists = new ArrayList<>();
List<List<Object>> finalList = new ArrayList<>();

// each list contains => code,   name,   version
lists.add(Arrays.asList("code1", "Name1", 1));
lists.add(Arrays.asList("code1", "Name1", 2));
lists.add(Arrays.asList("code1", "Name1", 3));
lists.add(Arrays.asList("code1", "Name1", 3));
lists.add(Arrays.asList("code2", "Name2", 1));
lists.add(Arrays.asList("code2", "Name2", 2));

// get all uniqueCodes
List<Object> uniqueCodes = lists.stream().map(row -> row.get(0)).distinct().collect(Collectors.toList());

// iterate over uniqueCodes 
uniqueCodes.stream().forEach(code -> {
    // get lists for this uniqueCode
    Supplier<Stream<List<Object>>> sameCodeLists = () -> lists.stream().filter(row -> row.get(0) == code);

    // get max version of this uniqueCode
    int maxVersion = sameCodeLists.get().mapToInt(row -> (int) row.get(2)).max().getAsInt();

    // for this uniqueCode, get all Lists containing Max Version
    finalList.addAll(sameCodeLists.get().filter(row -> (int) row.get(2) == maxVersion && row.get(0) == code).collect(Collectors.toList()));
});
System.out.println(finalList);

这是适当的,正如预期的那样。寻找代码优化,以较少的迭代完成任务。

通过

  • 创建一个类并使用它的实例而不是
    List
    s
  • 使用
    采集器。分组方式
    采集器。maxBy

更新 这不是一个简单的任务,所以流API可能不适合。尽管如此,我还是想出了下面的方法,似乎可以做到这一点

List<Entity> result = entities.stream()
    // group by code and sort the resulting lists by version
    .collect(groupingBy(Entity::getCode, HashMap::new,
            collectingAndThen(toList(), e -> e.stream().sorted(comparingInt(Entity::getVersion).reversed()).collect(toList()))))
    .values()
    .stream()
    // keep only the max values
    .map(l -> l.size() > 0 ? l.stream().filter(i -> i.getVersion() == l.get(0).getVersion()).collect(toList()) : l)
    .flatMap(List::stream)
    .collect(toList());

System.out.println(result);
// [
//  Entity(code=code2, name=Name2, version=2), 
//  Entity(code=code1, name=Name1, version=3), 
//  Entity(code=code1, name=Name1, version=3)
// ]
List result=entities.stream()
//按代码分组并按版本对结果列表排序
.collect(groupingBy)(实体::getCode,HashMap::new,
收集然后(toList(),e->e.stream().sorted(comparingInt(Entity::getVersion).reversed()).collect(toList()))
.values()
.stream()
//只保留最大值
.map(l->l.size()>0?l.stream().filter(i->i.getVersion()==l.get(0.getVersion()).collect(toList()):l)
.flatMap(列表::流)
.collect(toList());
系统输出打印项次(结果);
// [
//实体(代码=代码2,名称=名称2,版本=2),
//实体(代码=代码1,名称=名称1,版本=3),
//实体(代码=代码1,名称=名称1,版本=3)
// ]

您可以通过

  • 创建一个类并使用它的实例而不是
    List
    s
  • 使用
    采集器。分组方式
    采集器。maxBy

更新 这不是一个简单的任务,所以流API可能不适合。尽管如此,我还是想出了下面的方法,似乎可以做到这一点

List<Entity> result = entities.stream()
    // group by code and sort the resulting lists by version
    .collect(groupingBy(Entity::getCode, HashMap::new,
            collectingAndThen(toList(), e -> e.stream().sorted(comparingInt(Entity::getVersion).reversed()).collect(toList()))))
    .values()
    .stream()
    // keep only the max values
    .map(l -> l.size() > 0 ? l.stream().filter(i -> i.getVersion() == l.get(0).getVersion()).collect(toList()) : l)
    .flatMap(List::stream)
    .collect(toList());

System.out.println(result);
// [
//  Entity(code=code2, name=Name2, version=2), 
//  Entity(code=code1, name=Name1, version=3), 
//  Entity(code=code1, name=Name1, version=3)
// ]
List result=entities.stream()
//按代码分组并按版本对结果列表排序
.collect(groupingBy)(实体::getCode,HashMap::new,
收集然后(toList(),e->e.stream().sorted(comparingInt(Entity::getVersion).reversed()).collect(toList()))
.values()
.stream()
//只保留最大值
.map(l->l.size()>0?l.stream().filter(i->i.getVersion()==l.get(0.getVersion()).collect(toList()):l)
.flatMap(列表::流)
.collect(toList());
系统输出打印项次(结果);
// [
//实体(代码=代码2,名称=名称2,版本=2),
//实体(代码=代码1,名称=名称1,版本=3),
//实体(代码=代码1,名称=名称1,版本=3)
// ]

更好的设计是创建一个包含代码、名称、版本的类,然后您可以只使用
List
而不是
List
。它将使您的代码更干净、更可读、更易于维护。更好的设计是创建一个包含代码、名称、版本的类,这样您就可以使用
List
而不是
List
。它将使您的代码更干净、更可读和可维护。我在IDE上做了类似的事情,但得出的结论是使用
toMap
,我建议这种方法避免将
可选的
作为映射值,即
entities.stream().collect(toMap(Entity::getCode、Function.identity()、BinaryOperator.maxBy(Comparator.comparingInt(Entity::getVersion)))
或者您可以继续使用当前的方法,但使用
收集,然后使用
和finisher函数来获取
地图
。另外,另一个注意事项是,赞成
比较
而不是
比较
@Aomine谢谢。是的,我正在考虑一个finisher,这就是我想要的。@Aomine当然,它应该是
 比较IT
@andreTobilko/@Aomine-如果您观察问题中的输出,则需要收集具有最大版本的所有列表元素。在您的答案中,实体条目:[“code1”,“Name1”,3]是两次。由于允许重复条目,所以输出也应该包含两个条目。最终输出应该是一个列表,我们可以尝试不使用Map吗?我在IDE上做了类似的事情,但得出的结论是使用
toMap
,我建议使用这种方法来避免将
可选的
作为Map值,即
entities.stream().collect(toMap(Entity::getCode,Function.identity(),BinaryOperator.maxBy(Comparator.comparingit(Entity::getVersion)))
或者您可以继续使用当前的方法,但使用
收集,然后使用
和finisher函数来获取
地图
。另外,另一个注意事项是,赞成
比较
而不是
比较
@Aomine谢谢。是的,我正在考虑一个finisher,这就是我想要的。@Aomine当然,它应该是
 比较IT
@andreTobilko/@Aomine-如果您观察问题中的输出,则需要收集具有最大版本的所有列表元素。在您的回答中,实体条目:[“code1”,“Name1”,3]是两倍。由于允许重复条目,因此输出还应包含两个条目。最终输出应为列表,我们可以尝试不使用映射吗?
Map<String, Optional<Integer>> result = entities.stream()
  .collect(groupingBy(Entity::getCode,
    collectingAndThen(maxBy(Comparator.comparingInt(Entity::getVersion)),
      opEntity -> opEntity.map(Entity::getVersion))));

System.out.println(result);
// {code2=Optional[2], code1=Optional[3]}
List<Entity> result = entities.stream()
    // group by code and sort the resulting lists by version
    .collect(groupingBy(Entity::getCode, HashMap::new,
            collectingAndThen(toList(), e -> e.stream().sorted(comparingInt(Entity::getVersion).reversed()).collect(toList()))))
    .values()
    .stream()
    // keep only the max values
    .map(l -> l.size() > 0 ? l.stream().filter(i -> i.getVersion() == l.get(0).getVersion()).collect(toList()) : l)
    .flatMap(List::stream)
    .collect(toList());

System.out.println(result);
// [
//  Entity(code=code2, name=Name2, version=2), 
//  Entity(code=code1, name=Name1, version=3), 
//  Entity(code=code1, name=Name1, version=3)
// ]