Stream的API使用-flatMap

1,201 阅读1分钟

Stream->flatMap (扁平化处理)

场景一

有这样一个结构:

[ [ 1, 2, 3 ], [ 4, 5, 6 ] ]

想将其转换成这样的结构:

[ 1, 2, 3, 4, 5, 6 ]

怎么实现?

数据准备:

public class FlatMapTest {

    public static final List<List<Integer>> LIST = new ArrayList<>();

    static{
        LIST.add(Arrays.asList(1,2,3));
        LIST.add(Arrays.asList(4,5,6));
    }
}

方案一:for循环

@Test
public void test1(){
    Set<Integer> flatMapSet = new HashSet<>();
    LIST.forEach(flatMapSet::addAll);

    flatMapSet.forEach(System.out::println);
}

方案二:flatMap

@Test
public void test2() {
    Set<Integer> flatMapSet = LIST.stream().flatMap(Collection::stream).collect(Collectors.toSet());

    flatMapSet.forEach(System.out::println);
}

小结:

除了for循环,java8的Stream还专门提供了“扁平化”处理集合的API

for循环 VS flatMap

在场景一下,代码实现上从代码的优雅简洁程度上来看,二者差不多。如果稍微复杂一点呢?比如现在想把1给过滤掉。

方案一:for循环

@Test
public void test11(){
    Set<Integer> flatMapSet = new HashSet<>();
    LIST.forEach(l->{
        for (Integer integer : l) {
            if (integer != 1){
                flatMapSet.add(integer);
            }
        }
    });

    flatMapSet.forEach(System.out::println);
}

方案二:flatMap

@Test
public void test22() {
    Set<Integer> flatMapSet = LIST.stream()
            .flatMap(Collection::stream)
            .filter(f -> f != 1)
            .collect(Collectors.toSet());

    flatMapSet.forEach(System.out::println);
}

对比

增加了一点点复杂度之后,显然使用flatMap更优雅

结论

遇到这种需扁平化处理集合元素的场景下,直接选择使用flatMap,不要使用for循环,1来是for循环不够优雅,2是for循环可扩展性很差

flatMap参数解析

<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);

参数是一个Function,Function的出参是一个Stream,也就是说需要提供一个可以将元素转换成Stream的方法

比如:

java.util.Collection#stream java.util.stream.Stream#of(T)

其它案例场景

@Test
public void test3() {

    // 将所有字符串按"-"分割然后放到一个大集合中
    List<String> list = Arrays.asList("AB-CD", "AB-EF-GH", "IG-KL");

    Set<String> flatMapSet = list.stream()
            .flatMap(f -> {
                String[] arr = f.split("-");
                return Stream.of(arr);
            })
            .collect(Collectors.toSet());
    
    flatMapSet.forEach(System.out::println);
}