Java Streams在同一列表上循环两次

时间:2018-07-02 07:22:44

标签: java loops java-8 nested java-stream

我是Java 8的新手,出于某种原因,我在理解流时遇到问题。假设我们有一个对象列表List ,其中MyObject具有2个字段:Long Id,Date insertTime和我想删除具有相同ID和更早时间的元素。

对于2个for循环,它是这样的:

for(MyObject object : myObjects) {
   for(MyObject tmpObject : myObjects) {
      if(object.getId() == tmpObject.getId()) {
         if(object.getInsertDate().after(tmpObject.getInsertDate())) 
           myObjects.remove(tmpObject);
         else 
           myObjects.remove(object);
      }
   }
}

使用流时的外观如何?

@Michael,我不好。比起我,我需要另一个列表或数组来存储响应数据。

假设我有

  1. 1234:1991年5月25日
  2. 1235:25/5/1995
  3. 1234:25/5/1999

因此,我需要

  1. 1235:25/5/1995
  2. 1234:25/5/1999

谢谢大家。

2 个答案:

答案 0 :(得分:7)

按ID分组,然后为每个ID选择插入日期最大的ID。您可以用MyObject替换Sample。

    Map<Long, List<Sample>> map = list.stream().collect(Collectors.groupingBy(Sample::getId));
    map.values().stream()
            .map(samples -> Collections.max(
                    samples, Comparator.comparing(Sample::getInsertDate)))
            .collect(Collectors.toList());

答案 1 :(得分:1)

您可以这样做

List<MyObject> latestObjects = myObjects.stream()
    .collect(Collectors.collectingAndThen(
        Collectors.groupingBy(MyObject::getId,
            Collectors.maxBy(Comparator.comparing(MyObject::getInsertTime))),
        map -> map.values().stream().map(op -> op.orElse(null)).collect(Collectors.toList())));

首先将对象按其ID值分组,然后将其减少以仅保留每个ID值的最新对象,最后将它们收集到List中。

更新

这可以根据下面的评论进一步加以改进。这是它的增强版。

List<MyObject> latestObjects = myObjects.stream()
        .collect(Collectors.collectingAndThen(
                Collectors.toMap(MyObject::getId, Function.identity(),
                        BinaryOperator.maxBy(Comparator.comparing(MyObject::getInsertTime))),
                map -> new ArrayList<MyObject>(map.values())));