如何在Java中生成列表的所有k子列表?

3

让我们考虑:List <String> ints = Arrays.asList("1","2","3","4","5","6"),并且让k=2

我们想要返回以下列表 List<String> : ["12", "23", "34", "45", "56"]

优雅的解决方案呢?有没有可能使用流来实现?

当然可以用多种方式解决,最简单的方法是迭代整个列表并使用嵌套列表 1...k

有什么想法吗?


2
使用流来同时访问多个元素并不是很优雅。为什么不用迭代呢?它简单易懂,容易调试。 - IEE1394
“16”也是子列表吗? - dehasi
2
这是可能的,而且可能会有人发布一个复杂的解决方案。标准的Java 8流对于此不太好,要么不使用它们,要么使用更好的流库。 - Oleg
一些使用流(Stream)而非for循环的想法:http://www.deadcoderising.com/2015-05-19-java-8-replace-traditional-for-loops-with-intstreams/ - IEE1394
2个回答

4

使用流:

        final List<String> ints = Arrays.asList("1", "2", "3", "4", "5", "6");
        final int k = 2;
        final List<String> result = IntStream.iterate(0, i -> i + 1).limit(ints.size() - k + 1)
                .mapToObj(i -> ints.subList(i, i + k).stream().reduce("", (a, b) -> a + b + ""))
                .collect(Collectors.toList());

        System.out.println(result);3

使用for循环:

    List<String> result = new LinkedList<>();
    for(int i = 0 ; i < ints.size() - k + 1; i++) {
        StringBuilder sb = new StringBuilder();
        for(int j = 0; j < k; j++) {
            sb.append(ints.get(i+j));
        }
        result.add(sb.toString());
    }

    System.out.println(result);

现在你自己决定吧 ;-)

4
如果你可以接受结果是Collection<String>而不是List<String>,那么你可以使用Java 9的Collectors.flatMapping
Collection<String> result = IntStream.range(0, ints.size() - k)
    .boxed()
    .collect(Collectors.groupingBy(i -> i, 
        Collectors.flatMapping(i -> ints.subList(i, i + k).stream(), 
            Collectors.joining())))
    .values();

另一种方式,类似于IEE1394的答案

List<String> result = IntStream.range(0, ints.size() - k)
    .mapToObj(i -> String.join("", ints.subList(i, i + k)))
    .collect(Collectors.toList());

嗨@Eugene!谢谢!我喜欢第二个,但你知道...我认为我更喜欢一种常见的命令式方法... - fps
你可以将结果传递给 new ArrayList<>() 构造函数,以获取一个列表返回。 - Lino

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接