2017-12-16 4 views
3

です。以下のようなクラスがあります。Java 8コレクションの最大サイズは

class Student { 
    public Student(Set<String> seminars) { 
     this.seminar = seminars; 
    } 
    Set<String> seminar; 
    public Set<String> getSeminar() 
    { 
     return seminar; 
    } 
} 

そして、以下のような生徒を作成しました。

List<Student> students = new ArrayList<Student>(); 
Set<String> seminars = new HashSet<String>(); 

seminars.add("SeminarA"); 
seminars.add("SeminarB"); 
seminars.add("SeminarC"); 

students.add(new Student(seminars)); //Student 1 - 3 seminars 
students.add(new Student(seminars)); //Student 2 - 3 seminars 

seminars = new HashSet<String>(); 
seminars.add("SeminarA"); 
seminars.add("SeminarB"); 

students.add(new Student(seminars)); //Student 3 - 2 seminars 

seminars = new HashSet<String>(); 
students.add(new Student(seminars)); //Student 4 - 0 seminars 

今の質問は、あなたが3(最大値)のセミナーに出席した学生2名がある見ることができるように「私はMaximusのセミナーをattenededた学生の数を取得しようとしている」ので、私はするのに必要なそのカウントを取得します。

私はストリーム

OptionalInt max = students.stream() 
    .map(Student::getSeminar) 
    .mapToInt(Set::size) 
    .max(); 
long count = students.stream() 
    .map(Student::getSeminar) 
    .filter(size -> size.size() == max.getAsInt()) 
    .count(); 

を使用して2つの異なる文を使用して同じことを達成し1つのステートメントを使用して同じことを達成するための方法は何ですか?

答えて

2

、follwingコードを使用してください:

students.stream() 
    .map(Student::getSeminar) 
    .collect(Collectors.groupingBy(Set::size, Collectors.counting())); 

あなたの出力は次のようになります。

{0=1, 2=1, 3=2} 

あなたが見ることができるように、セミナーの最大数に行くtwo studentsがあります3つです。

最初に、すべての生徒オブジェクトをストリームから実際のセットに変更し、次にCollectors groupingBy()メソッドを使用してセットをサイズ別にグループ化しました。

あなたが学生の数だけを取得したい場合は、次のコードを使用してください:

students.stream() 
    .map(Student::getSeminar) 
    .collect(Collectors.groupingBy(Set::size, Collectors.counting())) 
    .values().stream() 
    .max(Comparator.comparing(a->a)) 
    .get(); 

をあなたの出力は次のようになります。2

+0

あなたが最後 – Lino

+1

に過度の1つのブラケットを持っ屋ああ、それは正しいです。ただそれを削除します。ありがとう@ Lino –

+0

何か問題はありませんか?あなたは上記のコードを試しましたか? –

0

これは醜いですが、次のように動作します:

long count = students.stream() 
    .filter(s -> s.getSeminar().size() == students 
     .stream().mapToInt(a -> a.getSeminar().size()) 
     .max().orElse(0)) 
    .count(); 

説明:これは、学生のリストをストリームやセミナーの最大数(とのみ学生は、ネストされたラムダが何であるかであるように、学生をフィルタリング)が残り、そのストリームのカウントを取得します。この問題を解決するには

0

はリトル最も実用的な状況では、グループ化

TreeMap<Integer, Long> agg = students.stream() 
      .map(Student::getSeminar) 
      .collect(Collectors.groupingBy(Set::size, TreeMap::new, Collectors.counting())); 
    System.out.println(agg); 
    System.out.println(agg.lastEntry().getKey() + " - " + agg.lastEntry().getValue()); 

出力

3 - 2 
1

をしながら、キーをソートするために、アレックスのソリューション@修正、二度リストを横断するあなたのアプローチは、最高のものです。それは簡単で、コードは分かりやすいです。声明を保存するように促す - セミコロンごとに請求されることはありません!

ただし、ソースデータを2回トラバースできないシナリオが考えられます。おそらく、それはネットワークストリームのような遅いまたは一度だけのソースから来るでしょう。

このような状況が発生した場合は、すべてのmax要素をダウンストリームコレクタに収集するカスタムコレクタallMaxByを定義することができます。

次にあなたが

long maxCount = students.stream() 
    .collect(allMaxBy(
      comparingInt(s -> s.getSeminar().size()), 
      counting() 
    )); 

を書くことができるだろう。ここallMaxByのための実装です:

public static <T, A, R> Collector<T, ?, R> allMaxBy(Comparator<? super T> cmp, Collector<? super T, A, R> downstream) { 
    class AllMax { 
     T val; 
     A acc = null; // null means empty 

     void add(T t) { 
      int c = acc == null ? 1 : cmp.compare(t, val); 
      if (c > 0) { 
       val = t; 
       acc = downstream.supplier().get(); 
       downstream.accumulator().accept(acc, t); 
      } else if (c == 0) { 
       downstream.accumulator().accept(acc, t); 
      } 
     } 

     AllMax merge(AllMax other) { 
      if (other.acc == null) { 
       return this; 
      } else if (this.acc == null) { 
       return other; 
      } 
      int c = cmp.compare(this.val, other.val); 
      if (c == 0) { 
       this.acc = downstream.combiner().apply(this.acc, other.acc); 
      } 
      return c >= 0 ? this : other; 
     } 

     R finish() { 
      return downstream.finisher().apply(acc); 
     } 
    } 

    return Collector.of(AllMax::new, AllMax::add, AllMax::merge, AllMax::finish); 
} 
+0

'セミコロンごとに請求されることはありません。' - それはとても良いでしょう。 – Eugene

関連する問題