我有一个 List<Person> persons = new ArrayList<>();
,我想列出所有的独特姓名。我的意思是,如果有"John"、"Max"、"John"、"Greg",那么我只想列出"Max"和"Greg"。是否有一种使用Java流实现的方式?
我有一个 List<Person> persons = new ArrayList<>();
,我想列出所有的独特姓名。我的意思是,如果有"John"、"Max"、"John"、"Greg",那么我只想列出"Max"和"Greg"。是否有一种使用Java流实现的方式?
Collectors.groupingBy
来计算每个名称出现的次数,然后过滤掉出现超过一次的任何名称: List<String> res = persons.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.filter(e -> e.getValue() == 1)
.map(e -> e.getKey())
.collect(Collectors.toList());
System.out.println(res); // [Max, Greg]
List persons = new ArrayList();
persons.add("Max");
persons.add("John");
persons.add("John");
persons.add("Greg");
persons.stream()
.filter(person -> Collections.frequency(persons, person) == 1)
.collect(Collectors.toList());
O(n^2)
,非常低效。 - fps这是我的解决方案:
List<String> persons = new ArrayList<>();
persons.add("John");
persons.add("John");
persons.add("MAX");
persons.add("Greg");
persons.stream()
.distinct()
.sorted()
.collect(Collectors.toList());
首先猜测解决方案。
persons.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.filter(entry -> entry.getValue() == 1)
.map(Map.Entry::getKey)
.collect(Collectors.toList())
public static <T> Collector<T, ?, List<T>> excludingDuplicates() {
return Collector.<T, Map<T, Boolean>, List<T>>of(
LinkedHashMap::new,
(map, elem) -> map.compute(elem, (k, v) -> v == null),
(left, right) -> {
right.forEach((k, v) -> left.merge(k, v, (o, n) -> false));
return left;
},
m -> m.keySet().stream().filter(m::get).collect(Collectors.toList()));
}
Collector.of
来创建一个自定义收集器,它将在LinkedHashMap
上累积元素:如果元素不存在于键中,则其值将为true
,否则将为false
。合并函数仅应用于并行流,它将right
映射合并到left
映射中,通过尝试将right
映射的每个条目放入left
映射中,并将已存在键的值更改为false
。最后,完成函数返回一个列表,其中包含值为true
的映射键。
该方法可按以下方式使用:
List<String> people = Arrays.asList("John", "Max", "John", "Greg");
List<String> result = people.stream().collect(excludingDuplicates());
System.out.println(result); // [Max, Greg]
这里有比使用自定义收集器更简单的方法:
Map<String, Boolean> duplicates = new LinkedHashMap<>();
people.forEach(elem -> duplicates.compute(elem, (k, v) -> v != null));
duplicates.values().removeIf(v -> v);
Set<String> allUnique = duplicates.keySet();
System.out.println(allUnique); // [Max, Greg]
List<Person> uniquePersons = personList.stream()
.collect(Collectors.groupingBy(person -> person.getName()))
.entrySet().stream().filter(stringListEntry -> stringListEntry.getValue().size()==1)
.map(stringListEntry -> { return stringListEntry.getValue().get(0); })
.collect(Collectors.toList());
这将删除所有重复的元素。
List<String> persons = new ArrayList<>();
persons.add("John");
persons.add("John");
persons.add("MAX");
persons.add("Greg");
Set<String> set = new HashSet<String>();
Set<String> duplicateSet = new HashSet<String>();
for (String p : persons) {
if (!set.add(p)) {
duplicateSet.add(p);
}
}
System.out.println(duplicateSet.toString());
set.removeAll(duplicateSet);
System.out.println(set.toString());
Collections.frequency
来检查列表中元素的出现次数,如下所示,以过滤重复项:List<String> listInputs = new ArrayList<>();
//add your users
List<String> listOutputs = new ArrayList<>();
for(String value : listInputs) {
if(Collections.frequency(listInputs, value) ==1) {
listOutputs.add(value);
}
}
System.out.println(listOutputs);
John
,因为它是一个重复项! - Nir Alfasi