简体   繁体   English

如何从列表中获取最新对象的列表

[英]How to get the list of latested objects from a list

I have a list of objects (instance of class A):我有一个对象列表(A 类的实例):

Class A {
  private String name;
  private Date createdDate;
}

List [
A ("a", 01-Jan-2017),
A ("a", 03-Jan-2017),
A ("a", 02-Jan-2017),
A ("b", 05-Jan-2017),
A ("b", 06-Jan-2017),
A ("b", 07-Jan-2017),
.
.
.
A ("x", 02-Jan-2017),
A ("x", 05-Jan-2017),
A ("x", 06-Jan-2017),
A ("x", 07-Jan-2017)
]

How can I extract a list of class A for each 'name' with latest createdDate.如何使用最新的 createdDate 为每个“名称”提取 A 类列表。

I,e, expected output is -我,e,预期输出是 -

List [
    A ("a", 03-Jan-2017),
    A ("b", 07-Jan-2017),
    .
    .
    .
    A ("x", 07-Jan-2017)
    ]
yourList.stream()
        .collect(Collectors.groupingBy(
               A::getName,
               Collectors.collectingAndThen(
                      Collectors.maxBy(Comparator.comparing(A::getCreatedDate)), 
                      Optional::get)))
        .values();

This will return a Collection<A> , which you can put into an ArrayList for example if needed.这将返回一个Collection<A> ,如果需要,您可以将其放入ArrayList中。

EDIT编辑

As suggested by Holger, a better way:正如 Holger 所建议的,更好的方法是:

...
.stream()
.collect(Collectors.toMap(
               A::getName,
               Function.identity(),
               BinaryOperator.maxBy(Comparator.comparing(A::getCreatedDate))))
.values();

By making A implement Comparable<A> you can define a custom ordering based on the createdDate field.通过使A实现Comparable<A>您可以根据createdDate字段定义自定义排序。

class A implements Comparable<A> {
    private String name;
    private Date createdDate;
    public A(String name, Date createdDate) {
        this.name = name;
        this.createdDate = createdDate;
    }

    @Override
    public int compareTo(A other) {
        return createdDate.compareTo(other.createdDate); // provided you're using java.util.Date here
    }

    public static void main(String[] args) {
        List<A> aList = ... // Create your list here
        Collections.sort(aList);
        System.out.println(aList);
    }
}

After calling Collections.sort(aList) your list should be sorted based on the ordering you've implemented.在调用Collections.sort(aList)您的列表应该根据您实现的顺序进行排序。

Then, you can iterate the sorted list and stop, whenever an element has a date later than what you're checking for.然后,只要元素的日期晚于您要检查的日期,就可以迭代已排序的列表并停止。

This is my example :这是我的例子:
first sort by name and then sort by date .首先按名称排序,然后按日期排序。

public class MainClass {
    public static void main(String[] args) {
        List<A> aList = new ArrayList<>();
        aList.add(new A("a",new Date(2017,11,3)));
        aList.add(new A("b",new Date(2017,3,3)));
        aList.add(new A("a",new Date(2017,11,9)));
        aList.add(new A("a",new Date(2017,1,23)));
        aList.add(new A("b",new Date(2017,8,15)));

        aList.stream().sorted(Comparator.comparing(A::getName).thenComparing(A::getCreateDate))
                .filter(distinctByKey(A::getName))
                .forEach(System.out::println);
    }

    private static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor)
    {
        Map<Object, Boolean> map = new ConcurrentHashMap<>();
        return t -> map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }
}

example output :示例输出:

A{name='a', createDate=Fri Feb 23 00:00:00 IRST 3917}
A{name='b', createDate=Tue Apr 03 00:00:00 IRDT 3917}

if you need collection :如果您需要收集:
replace foreach to .collect(Collectors.toList()) .将 foreach 替换为 .collect(Collectors.toList()) 。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM