2017-04-07 3 views
-1

私はList<Person> persons = new ArrayList<>();を持っていて、すべてのユニークな名前をリストしたいと思います。私は "ジョン"、 "マックス"、 "ジョン"、 "グレッグ"がある場合、 "マックス"と "グレッグ"だけをリストしたいと思います。 Javaストリームでそれを行うにはいくつかの方法がありますか?Javaストリーム - ユニークな要素を見つける

+1

は、最初のいくつかの基本的な研究を行って試してみてくださいwww.google.co.uk/search?q=java%20stream%20unique –

+0

それをストリームに集めてストリーム:)実際には、あなたがそのオーダーを気にしなければ、ただセットしてください。 – 9000

+2

あなたの側で任意のコードの試行ですか? – MaxZoom

答えて

7

私たちはどのように多くの発生をカウントするために、ストリームやCollectors.groupingByを使用することができます:あなたは、単に以下に示すように、重複をフィルタリングするために、リストで要素のoccuranceをチェックする使用Collections.frequencyでき

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

これにより、重複する要素がすべて削除されます。

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

私たちはそれぞれの名前を持っています - 複数の名前が一度だけフィルタリングされます:

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] 
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になります。マージ機能はパラレルストリームにのみ適用され、leftマップの各エントリをleftマップに配置し、すでに存在するキーの値をfalseに変更することで、rightマップをleftマップにマージします。最後にフィニッシャー関数は、値がtrueのマップのキーを含むリストを返します。次のように

この方法を使用することができます。

List<String> people = Arrays.asList("John", "Max", "John", "Greg"); 

List<String> result = people.stream().collect(excludingDuplicates()); 

System.out.println(result); // [Max, Greg] 

そして、ここでは別のアプローチは、カスタムコレクタを使用するよりも簡単です:します。https://

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] 
関連する問題