我试图利用Java的功能库来过滤掉List中的一些条目。
我有一个Book对象列表,首先按书本ID排序,然后按修订号排序。下面的示例我在列表中有九个Book对象。
Book: ID 1, Revision Number 1
Book: ID 1, Revision Number 2
Book: ID 1, Revision Number 3
Book: ID 2, Revision Number 1
Book: ID 2, Revision Number 2
Book: ID 2, Revision Number 3
Book: ID 3, Revision Number 1
Book: ID 3, Revision Number 2
Book: ID 3, Revision Number 3
我想过滤列表,以便每个图书ID只有最高版本号。
Book: ID 1, Revision Number 3
Book: ID 2, Revision Number 3
Book: ID 3, Revision Number 3
Java是否具有使用过滤器或比较器之类的功能,以允许我根据公共值(书籍ID)基于多个字段进行过滤?我想尝试避免编写我自己的函数来循环收集并尽可能地进行过滤......有什么建议吗?
答案 0 :(得分:4)
这样的事情:
List<Book> books = Arrays.asList(
new Book(1, 2),
new Book(1, 3),
new Book(2, 2),
new Book(2, 3)
);
System.out.println(
books.stream()
.collect(
groupingBy(Book::getID,
maxBy(comparingInt(Book::getRevison))
)
)
);// {1=Optional[Book{ID=1, revison=3}], 2=Optional[Book{ID=2, revison=3}]}
如果最后更新,您只需List<Book>
只需使用Map<Integer,Optinal<Book>>
.values().stream().map(Optional::get).collect(Collectors.toList()));
完整的例子:
System.out.println(books.stream()
.collect(
groupingBy(Book::getID,
maxBy(comparingInt(Book::getRevison))
)
).values()
.stream()
.map(Optional::get)
.collect(Collectors.toList())
);
答案 1 :(得分:0)
这不是基于多个属性的真正过滤,但可以解决您的问题:
final Map<String, Book> books = list.stream().collect(
Collectors.toMap(
b -> b.getId(),
b -> b,
(b1, b2) -> {
if(b1.getNumber() > b2.getNumber()) {
return b1;
}
return b2;
})
);
它将返回包含id作为键的map,以及具有最高编号的book(具有唯一id)。
在toMap
收集器中,您可以添加merge function
,这将决定在相同密钥发生冲突时要执行的操作。在这种情况下,它将返回更高数字的书。
如果您想要通过该电话values()
收集。