如何使用java 8 stream从基于多个条件的列表中获取distinct元素?
例如 - 让我们假设一个对象Person
:
class Person {
Integer id;
String name;
}
我想要一个包含id
和name
唯一组合的列表
列表
答案 0 :(得分:5)
您可以创建自己独特的方法,例如:
private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Map<Object, Boolean> seen = new ConcurrentHashMap<>();
return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
所以你可以将它与过滤器一起使用:
List<Person> persons = listPersons.stream()
//@Holger suggest
.filter(distinctByKey(pr -> Arrays.asList(pr.getId(), pr.getName())))
.collect(toList());
看看这个:
如果您的名单是:
List<Person> listPersons = Arrays.asList(
new Person(1, "person1"),
new Person(1, "person5"),
new Person(2, "person2"),
new Person(1, "person1"),
new Person(1, "person2"),
new Person(1, "person1"),
new Person(3, "person3")
);
输出
Person{id=1, name=person1}
Person{id=1, name=person5}
Person{id=2, name=person2}
Person{id=1, name=person2}
Person{id=3, name=person3}
答案 1 :(得分:2)
为您的课程覆盖hashCode()
和equals()
方法,然后您可以执行以下操作:
Set<Person> result = persons.stream().collect(Collectors.toSet());
Set是一个不允许重复的数据结构,所以这样你只会有唯一的元素。
这是一个解决方案:https://ideone.com/e.js/G7T2rH
答案 2 :(得分:0)
方法Stream.distinct()
方法,返回唯一值流(基于Object.equals)
https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#distinct--
答案 3 :(得分:0)
我不确定,你究竟在寻找什么,但我前段时间遇到了类似的问题,这可能会有所帮助。
import java.util.ArrayList;
import java.util.List;
public class Person {
public int id;
public String name;
public static List<String> combinedIds;
public Person(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public static String getCombinedUuid(Person person) {
return person.getName() + person.getId();
}
public static void main(String[] args) {
List<String> combinedIDs = new ArrayList<String>();
Person person = new Person(12345, "Doe");
String generatedUuid = getCombinedUuid(person);
combinedIDs.add(generatedUuid);
System.out.println(combinedIDs.get(0).toString());
}
}
答案 4 :(得分:0)
您可以先过滤列表以获取符合条件的元素,然后使用distinct。
List<element> getDistinctForCrit(Filter<element> pred) {
//assuming list is already available in this class
return list.stream().filter(pred).distinct().collect(Collectors.toList())
}
您可以将过滤条件传递给此函数,然后distinct将为您获取唯一值。
distinct()
根据对象比较产生不同的值。
因此,您应该在类
的equals()方法中给出唯一性逻辑答案 5 :(得分:0)
下面是获取解决方案的步骤。
您需要在Person类中实现equals和hashcode以进行相等性检查。 如果您在类中重写了这些方法,则每当进行相等检查时,都会调用Person中实现的方法,并将始终返回唯一的结果。
class Person {
Integer id;
String name;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person p = (Person) o;
return id == p.id && Objects.equals(name, p.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
}
使用以下任何一种方法来获得与众不同的Person值:
a)。使用Set是因为Set仅包含唯一值。这是一个无序的集合。
Set<Person> set=new HashSet<Person>();
for(Person c:list){
set.add(c);
}
b)。使用Java8 Stream API:
List<Person> unique = list.stream().collect(collectingAndThen(toCollection(() -> new TreeSet<>(comparingInt(Person::getId))),
ArrayList::new));
c)。如果需要有序收集:
LinkedHashSet<Person> lset=new LinkedHashSet<Person>();
for(Personc:list){
lset.add(c);
}
d)Java 8 Stream API方法:
List<Person> ll= list.stream().distinct().collect(Collectors.toList());
ll.forEach((k) -> System.out.println(k.getId()+" & "+k.getName()));