java8 stream根据下标分组

我有个list想要按照奇偶下标生成两组list,只利用java8的stream可以做到吗?
比如[1,3,5,7,9],按照奇偶下标分成[1,5,9]和[3,7],但是stream似乎无法获取下标,所以试了半天也不行。
另外,java8的stream以后可以完全取代for循环吗?我感觉有些复杂的逻辑拿stream折腾不是一个好的选择

阅读 16.5k
3 个回答

这个要从为什么java8会弄出stream这种循环方式说起了

以前的for循环是属于外部循环,由调用者自己显式的取出每个元素加以处理,尤其是并行处理时,非常痛苦

而stream是属于内部循环,你可以无需关心它是如何循环的,要是并行的时候如何优化,这些你都可以不管,你只需要简简单单告诉他需要做什么处理即可

举个简单的例子:

地上有很多乒乓球,爸爸要让你儿子捡起来放到盒子里
如果是外部循环,可能这种模式
爸爸:地上还有球么
儿子:有
爸爸:那把它捡起来放到盒子里,还有么?
儿子:有
爸爸:继续捡起来放到盒子里,还有么?
儿子:有
爸爸:接着捡起来放到盒子里,还有么?
儿子:没有了
爸爸:ok,收拾好了

如果是内部循环
爸爸:把地上的球捡起来全部放到盒子里
儿子:好,完成

例子可能很牵强,但是我们作为开发者,就是爸爸,只需要告诉儿子(JDK)把球放进盒子这个动作就好,具体儿子怎么放,一次一个手拿一个,还是一次每个手拿一个,由它自己来思考,不需要我们去指挥,我们只关注具体需要做的事就好

所以说stream是一种内部循环,你不需要去关注下标...关注下标的话,从某种意义上来说,还是外部循环的思想在处理了,当然题主的问题中,明确就是要求是关注下标了,貌似好像stream是没法写似的

其实不然,写肯定能写的,只是说换一种方式而已,不把下标当成循环用的元素,而是把它与具体需要循环的数字绑定起来,写出来差不多是这个样子

public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1,3,5,7,9);

        Map<Boolean, List<Integer>> collect = IntStream.rangeClosed(1, list.size())
                                                      .boxed()
                                                      // 把数字和下标绑定起来
                                                      .map(i -> mapToEntry(i, list.get(i-1)))
                                                      // 按照下标是否能被2整除进行分组
                                                      .collect(Collectors.partitioningBy(simpleEntry -> Integer.parseInt(simpleEntry.getKey().toString()) % 2 == 0,
                                                               Collectors.mapping(Map.Entry::getValue, Collectors.toList())));
        // 偶数列表 3,9
        List<Integer> evenList = collect.get(Boolean.TRUE);
        // 奇数列表 1,5,7
        List<Integer> oddList = collect.get(Boolean.FALSE);
    }

    private static AbstractMap.SimpleEntry<Integer, Integer> mapToEntry(Integer i, Integer integer) {
        return new AbstractMap.SimpleEntry(i, integer);
    }

stream是无法直接获取下标的,因为它的好处就是让我们忘记那让人懵逼的下标。

但还是可以曲线救国:

List<String> names = Arrays.asList("Sam", "Pamela", "Dave", "Pascal", "Erik");
IntStream.range(0, names.length)
         .filter(i -> i%2==0)
         .mapToObj(i -> names[i])
         .collect(Collectors.toList());

[1, 3, 5, 7, 9]的偶数下标数组:

    int[] i = new int[] {0};
    System.out.println(Arrays.toString(IntStream.of(1, 3, 5, 7, 9).filter(n -> i[0]++ % 2 == 0).toArray()));

得到[1, 5, 9]

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏