2017-04-07 91 views
-1

我有List<Person> persons = new ArrayList<>();,我想列出所有的唯一名称。我的意思是如果有“John”,“Max”,“John”,“Greg”,那么我只想列出“Max”和“Greg”。有什么方法可以用Java流来完成它吗?Java流 - 找到唯一的元素

+1

先尝试做一些基础研究:https://开头www.google.co.uk/search?q=java%20stream%20unique。 –

+0

把它收集到一个集合:)实际上,如果你不关心订单,就做一个集合。 – 9000

+2

任何代码尝试在你身边? – MaxZoom

回答

7

我们可以使用流和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] 
1

这应该删除所有重复的元素。

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()); 
1

你可以简单地使用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); 
4

首先猜解。

persons.stream() 
     .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())) 
     .entrySet() 
     .stream() 
     .filter(entry -> entry.getValue() == 1) 
     .map(Map.Entry::getKey) 
     .collect(Collectors.toList()) 
+3

伟大的思想家都认为... :) – alfasin

0
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()); 
0

这是旧的文章,但我想基于自定义收藏家提出另一种方法:

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]