使用java 8流生成整数对

时间:2015-08-04 16:32:04

标签: java lambda java-8 java-stream

我正在尝试生成整数对 - 我有一个类配对一个构造函数需要2个整数。以下代码有效,但看起来相当笨重 - 特别是使用mapToObj(Integer :: new)从intStream转换为对象流。

private static List<Pair> success() {
    return IntStream.range(0, 10).
            mapToObj(Integer::new).flatMap(i -> IntStream.range(12, 15).
                mapToObj(j -> new Pair(i, j))).
            collect(Collectors.toList());
}

首先,是否有人有更优雅的方式来做这件事?

其次,当我重构提取某些流作为变量时,我收到一个错误:IllegalStateException:stream已经被操作或关闭。这是重构的方法 - 有人知道这是代码的问题吗?

static List<Pair> fail() {
    Stream<Integer> outer = IntStream.range(0, 10).mapToObj(Integer::new);
    IntStream inner = IntStream.range(12, 15);
    Stream<Pair> pairStream = outer.flatMap(i -> 
            inner.mapToObj(j -> new Pair(i, j)));
    return pairStream.collect(Collectors.toList());
}

3 个答案:

答案 0 :(得分:3)

通过将mapToObj(Integer::new)替换为boxed,可以使其更简洁 - 但除此之外,Java并不简洁:

IntStream.range(0, 10)
        .boxed()
        .flatMap(i -> IntStream.range(12, 15)
                               .mapToObj(j -> new Pair(i, j)))
        .collect(Collectors.toList());

至于第二个问题:还有其他答案可以解决问题。具体问题是inner不会被使用一次,而是每次使用外flatMap()

这种方式有效:

        final IntStream range = IntStream.range(0, 10);
        List<Pair> ps =  range
               .boxed().flatMap(i -> {
                   final IntStream range1 = IntStream.range(12, 15);
                   return range1.
                           mapToObj(j -> new Pair<>(i, j));
               }).
            collect(Collectors.toList());

答案 1 :(得分:1)

为什么不使用普通for - 循环?普通for - 循环将:

  1. 看起来更好
  2. 明确你的意图
  3. static List<Pair> fail() {
        List<Pair> pairs = new ArrayList<>(30);
    
        for (int i = 0; i < 10; i++) {
            for (int j = 12; j < 15; j++) {
                pairs.add(new Pair(i, j));
            }
        }
    
        return pairs;
    }
    

答案 2 :(得分:0)

如果您的Pair类接受原始注入,则可以通过这种方式消除不必要的装箱:

private static List<Pair> success() {
    return IntStream.range(0, 10).
            mapToObj(i -> IntStream.range(12, 15).
                mapToObj(j -> new Pair(i, j))).
            flatMap(Function.identity()).
            collect(Collectors.toList());
}

至于将流提取为变量,您可以改为创建供应商:

private static List<Pair> success() {
    Supplier<IntStream> inner = () -> IntStream.range(12, 15);
    return IntStream.range(0, 10).
            mapToObj(i -> inner.get().
                mapToObj(j -> new Pair(i, j))).
            flatMap(Function.identity()).
            collect(Collectors.toList());
}

虽然我似乎没有必要将流提取到变量中。