2017-10-12 3 views
3

私はクラスのレベル(理解のためのダミークラス)を持っています。 levelIdに基づいてソートされたTreeMap<Level,Set<String>>が必要です。 コードの下に見つけてくださいストリームを使用してリストからTreeMapをソートする方法

import java.util.*; 
import java.util.stream.Collectors; 

    public class Level { 
     int levelId; 

     public Level(int levelId) { 
      this.levelId = levelId; 
     } 

     public static Level getLevel(String name){ 
      return new Level(name.length()); 
     } 

     public static void main(String[]args){ 
      Set<String> names=new HashSet<>(); 
      names.add("Mahesh"); 
      names.add("Ram"); 
      names.add("Rita"); 

      Map<Level, Set<String>> map = names.stream().collect(
        Collectors.groupingBy(name->Level.getLevel(name), 
        Collectors.mapping(name->name,Collectors.toSet()))); 

     } 
    } 

私もCollectors.collectingAndThen()で試してみました。

何か助けていただければ幸いです。

ありがとうございます。

+1

https://docs.oracle.com/javase/8/docs/api/java/util:次に、あなたはgroupingByコレクタにマップの工場として、この分離器を使用してTreeMapを作成するラムダ式を渡す必要があります/stream/Collectors.html#groupingBy-java.util.function.Function-java.util.function.Supplier-java.util.stream.Collector- –

+0

ストリームではなくforループを使用します。 –

+5

'Collectors.groupingBy(Level :: getLevel、TreeMap :: new、Collectors.toSet()) ' – 4castle

答えて

3

あなたはLevelComparableを実装させたくない場合は、Comparatorを必要としています。

public class Level { 
    int levelId; 

    public Level(int levelId) { 
     this.levelId = levelId; 
    } 

    public static Level getLevel(String name){ 
     return new Level(name.length()); 
    } 

    public int getLevelId() { 
     return levelId; 
    } 

    public static void main(String[]args){ 
     Set<String> names=new HashSet<>(); 
     names.add("Mahesh"); 
     names.add("Ram"); 
     names.add("Rita"); 

     Comparator<Level> c = Comparator.comparingInt(Level::getLevelId); 
     Map<Level, Set<String>> map = names.stream() 
      .collect(Collectors.groupingBy(
         Level::getLevel,() -> new TreeMap<>(c), Collectors.toSet())); 
    } 
} 
4

あなたの修正作業コードは次のようになり、4castleコメント@参照してください。私の意見では

public class Level implements Comparable<Level> { 
    int levelId; 

    public Level(int levelId) { 
     this.levelId = levelId; 
    } 

    @Override 
    public int compareTo(Level o) { 
     return Integer.compare(levelId, o.levelId); 
    } 

    public static Level getLevel(String name){ 
     return new Level(name.length()); 
    } 

    public static void main(String[]args){ 
     Set<String> names=new HashSet<>(); 
     names.add("Mahesh"); 
     names.add("Ram"); 
     names.add("Rita"); 

     Map<Level, Set<String>> map = names.stream().collect(
       Collectors.groupingBy(Level::getLevel, TreeMap::new, 
         Collectors.toSet())); 
    } 
} 
+1

はい、ちょうど答えを変更しました。 –

1

を、ストリームを使用しては、最も簡単な例では、読みやすさを向上させます。 Mapの具体的な実装が必要な場合や、カスタムComparatorを使用する必要がある場合は、forループを使用することを強く推奨します。はい、あなたは適切なメソッドのためにCollectorsクラスを検索することができますが、結果のコードは後でもう少し小さな変更を加える必要がある場合、柔軟性が低くなると信じています。

Java 8では、Mapインターフェイスには多くの改良が施されました。これは、このようなことをループで行うことは、これまでの場合よりもはるかに苦痛が少ないことを意味します。この場合

Map<Level, Set<String>> result = new TreeMap<>(Comparator.comparingInt(level -> level.levelId)); 
for (String name : names) 
    result.computeIfAbsent(getLevel(name), k -> new HashSet<>()).add(name); 

とにかくLevelキーでマップをしたい理由を、私はわかりません。あなたはidでグループ化したいので、キーがInteger sであることがより理にかなっていませんか?

Map<Integer, Set<String>> result = new TreeMap<>(); 
for (String name : names) 
    result.computeIfAbsent(getLevel(name).levelId, k -> new HashSet<>()).add(name); 
+2

質問の 'Level getLevel(String name)'メソッドは、実際の操作の単なるプレースホルダです。 [同様の実生活のクラス](https://docs.oracle.com/javase/8/docs/api/?java/util/logging/Level.html)があります。ところで、私は[ストリームベースのソリューション](https://stackoverflow.com/a/46704101/2711488)がループの代替方法より読みにくいとは思わない。ループがはるかに良い場合がありますが、ここでしきい値を超えているとは言えません。 – Holger

関連する問題