2017-11-22 4 views
4

私は考えているのJava 8:地図の<string、HashSetの<String>>

のJava 8のマップにN×Nのアレイをマップしたいを作成するために、アレイ(N×M個の)フィルタ毎[I] [その0]要素はキーであり、j> 0のすべての[i] [j]はマップ内のすべてのキーの値のリストです。

ありがとうございました。 :)

これは私のクラスである:

public class GroupingDishes { 

    public static void main(String[] args) { 

     String[][] dishes = { 
       {"Salad", "Tomato", "Cucumber", "Salad", "Sauce"}, 
       {"Pizza", "Tomato", "Sausage", "Sauce", "Dough"}, 
       {"Quesadilla", "Chicken", "Cheese", "Sauce"}, 
       {"Sandwich", "Salad", "Bread", "Tomato", "Cheese"} 
     }; 

     Map<String, HashSet<String>> groupDishes = groupingDishes(dishes); 
    } 

    public static Map<String, HashSet<String>> groupingDishes(String[][] dishes) { 

     Map<String, HashSet<String>> mapFood = new HashMap<>(); 

     for (int i = 0; i < dishes.length; i++) { 

      String food = dishes[i][0]; 

      for (int j = 0; j < dishes[i].length; j++) { 

       if (mapFood.containsKey(food)) { 

        HashSet<String> existingIngredients = mapFood.get(dishes[i][0]); 
        existingIngredients.add(dishes[i][j]); 
        mapFood.put(food, existingIngredients); 

       } else { 

        HashSet<String> newIngredient = new HashSet<>(); 
        mapFood.put(food, newIngredient); 

       } 
      } 
     } 
     return mapFood; 
    } 
} 

答えて

5

あなたはString[]のストリームにString[][]を変換することができ、 その後使用して、マップに を集めますキーとしてString[]の最初の項目、 、残りをセットの値として返します。

public static Map<String, HashSet<String>> groupingDishes2(String[][] dishes) { 
    return Arrays.stream(dishes) 
     .collect(Collectors.toMap(
      arr -> arr[0], 
      arr -> Arrays.stream(arr).skip(1).collect(Collectors.toCollection(HashSet::new)))); 
} 

ところで、私はあなたが本当にMap<String, HashSet<String>>を必要と疑います。 タイプをMap<String, Set<String>>, に変更して、実装を簡単に書くことができます。

public static Map<String, Set<String>> groupingDishes(String[][] dishes) { 
    return Arrays.stream(dishes) 
     .collect(Collectors.toMap(
      arr -> arr[0], 
      arr -> Arrays.stream(arr).skip(1).collect(Collectors.toSet()))); 
} 

またはより良い、@Holgerが示唆されているように、より良い代替、のでskiplimitでストリームは非常にうまく機能しない、またCollectors結果の初期容量のための任意のヒントを得ることはありません」。

public static Map<String, Set<String>> groupingDishes(String[][] dishes) { 
    return Arrays.stream(dishes) 
     .collect(Collectors.toMap(
      arr -> arr[0], 
      arr -> new HashSet<>(Arrays.asList(arr).subList(1, arr.length)))); 
} 
+1

2番目の関数ではなく、 'arr - > new HashSet <>(配列.asList(arr).subList(1、arr.length))'または 'リストを作成する' arr - > Arrays.asList(配列.copyOfRange(arr、1、arr.length)) '。 – Holger

+0

@Holger私はなぜサブリストが良いか知りたいのですが。仲介配列を使用する2番目の提案は、配列を作成するために配列が不要なため、それ以上のものはありません。 – janos

+4

提案に中間配列はありません。最初の提案は、元の配列をラップする*ビュー*からセットを作成します。 2番目の提案は、新しい配列を*ラップする*リストを作成します。いずれの提案もストリーム操作よりも短く効率的です。 'skip'と' limit'のストリームはうまく実行されません。また、 'Collector'は結果の初期容量のヒントを得ません。 – Holger

2

私はこれを考えることができます。

Map<String, HashSet<String>> result = Arrays.stream(dishes) 
      .map(x -> new AbstractMap.SimpleEntry<>(
        x[0], 
        Arrays.stream(x).skip(1).collect(Collectors.toCollection(HashSet::new)))) 
      .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); 
+4

だけ後続 'toMap'コレクタでそれらを抽出するために、中間' SimpleEntry'におけるキーと値を格納する必要はありません。 – Holger

関連する問題