目次
概要
Java Goldの資格勉強をしていて、StreamのflatmapというメソッドでCollection等を平坦化(ネストした配列等を同階層の要素としてまとめること)の挙動で、3階層以上のネスト構造ではどのように振舞うかが気になったので調べてみました。
確認したこと
3階層のネストしたListをflatmapした場合
◆結論
全てを平坦化はできず、1階層分のみ平坦化できる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
// 準備 List<String> firstNest1 = Arrays.asList("AAA", "BBB"); List<String> firstNest2 = Arrays.asList("CCC", "DDD"); List<String> firstNest3 = Arrays.asList("EEE"); List<String> firstNest4 = Arrays.asList("FFF"); List<List<String>> secondNest1 = new ArrayList<List<String>>(); List<List<String>> secondNest2 = new ArrayList<List<String>>(); List<List<List<String>>> thirdNest = new ArrayList<List<List<String>>>(); // 3層にネストしたList構造を生成 secondNest1.add(firstNest1); secondNest1.add(firstNest2); secondNest2.add(firstNest3); secondNest2.add(firstNest4); thirdNest.add(secondNest1); thirdNest.add(secondNest2); // flatmapで平坦化する前のList構造 // →[[[AAA, BBB], [CCC, DDD]], [[EEE], [FFF]]] System.out.print(thirdNest); // 3層構造のListをflatmapで出力(flatmapを1度だけ呼び出す) // [AAA, BBB][CCC, DDD][EEE][FFF] // →21階層分のみ平坦化できる。 thirdNest.stream() .flatMap(s -> s.stream()) .forEach(System.out::print); |
すべてを平坦化する方法
◆結論
ネストしたCollectionを再帰的に処理するメソッドを用意することで、すべての要素を平坦化する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
// 準備 // →「3階層のネストしたListをflatmapした場合」と同じ // 3層にネストしたList構造を生成 // →「3階層のネストしたListをflatmapした場合」と同じ // 3層構造のListをflatmapで出力(flattenメソッド) // →文字列に平坦化した例(3層までのネストを平坦化できている) // AAA BBB CCC DDD EEE FFF System.out.print(flatten(thirdNest) .map(Object::toString) .collect(Collectors.joining(" "))); // →Listに平坦化した例 // [AAA, BBB, CCC, DDD, EEE, FFF] System.out.print(flatten(thirdNest) .map(Object::toString) .collect(Collectors.toList())); /** * flatmap単独ではネストされた要素を平坦化できないため、 * 再帰的に平坦化することで実現する。 * @param o * @return */ public static Stream<Object> flatten(Object o) { if (o instanceof Object[]) { return Arrays.stream((Object[]) o).flatMap(e -> flatten(e)); } if (o instanceof Map<?, ?>) { return ((Map<?, ?>) o).entrySet().stream() .flatMap(e -> Stream.concat(flatten(e.getKey()), flatten(e.getValue()))); } if (o instanceof Collection<?>) { return ((Collection<?>) o).stream().flatMap(e -> flatten(e)); } if (o instanceof Stream<?>) { return ((Stream<?>) o).flatMap(e -> flatten(e)); } return Stream.of(o); } |
まとめ
- flatmapはネストした構造を平坦化できる。
- 3階層以上にネストされた構造は、再帰的に処理することですべての要素を平坦化できる。
コメント