在Java 8中显示分块项目列表

时间:2017-06-21 16:19:09

标签: list java-8 java-stream chunked

使用以下代码:

public class Main {

    public static void main(String[] args) {
        final List<Integer> items = 
             IntStream.rangeClosed(0, 23).boxed().collect(Collectors.toList());

        final String s = items
            .stream()
            .map(Object::toString)
            .collect(Collectors.joining(","))
            .toString()
            .concat(".");

        System.out.println(s);
    }
}

我明白了:

0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23

我想做的是每10个项目打破一行,以获得:

0,1,2,3,4,5,6,7,8,9,

10,11,12,13,14,15,16,17,18,19,

20,21,22,23。

google搜索后我尝试了很多东西但没有成功! 你能救我吗?

谢谢,

奥利弗。

3 个答案:

答案 0 :(得分:4)

如果您愿意使用第三方库,则以下内容将使用Eclipse Collections Collectors2.chunk(int)

String s = IntStream.rangeClosed(0, 23)
        .boxed()
        .collect(Collectors2.chunk(10))
        .collectWith(MutableList::makeString, ",")
        .makeString("", ",\n", ".");

Collectors2.chunk(10)的结果将是MutableList<MutableList<Integer>>。此时,我从Streams API切换到使用可直接在集合上使用的本机Eclipse Collections API。方法makeString类似于Collectors.joining()。方法collectWithStream.map()类似,区别在于将Function2和额外参数传递给方法。这允许在此使用方法引用而不是lambda。等效的lambda为list -> list.makeString(",")

如果您只使用Eclipse Collections API,则可以将此问题简化如下:

String s = Interval.zeroTo(23)
        .chunk(10)
        .collectWith(RichIterable::makeString, ",")
        .makeString("", ",\n", ".");

注意:我是Eclipse Collections的提交者。

答案 1 :(得分:3)

如果您只想处理这些升序号码,您可以像

那样进行处理
String s = IntStream.rangeClosed(0, 23).boxed()
    .collect(Collectors.groupingBy(i -> i/10, LinkedHashMap::new,
            Collectors.mapping(Object::toString, Collectors.joining(","))))
    .values().stream()
    .collect(Collectors.joining(",\n", "", "."));

此解决方案也可以适用于任意随机访问列表,例如

List<Integer> items = IntStream.rangeClosed(0, 23).boxed().collect(Collectors.toList());

String s = IntStream.range(0, items.size()).boxed()
    .collect(Collectors.groupingBy(i -> i/10, LinkedHashMap::new,
            Collectors.mapping(ix -> items.get(ix).toString(), Collectors.joining(","))))
    .values().stream()
    .collect(Collectors.joining(",\n", "", "."));

然而,对于任意流没有简单而优雅的解决方案,这种限制适用于对元素位置具有依赖性的所有类型的任务。

答案 2 :(得分:2)

以下是评论Collector中已经链接的改编:

    private static Collector<String, ?, String> partitioning(int size) {
    class Acc {
        int count = 0;

        List<List<String>> list = new ArrayList<>();

        void add(String elem) {
            int index = count++ / size;
            if (index == list.size()) {
                list.add(new ArrayList<>());
            }
            list.get(index).add(elem);
        }

        Acc merge(Acc right) {

            List<String> lastLeftList = list.get(list.size() - 1);
            List<String> firstRightList = right.list.get(0);
            int lastLeftSize = lastLeftList.size();
            int firstRightSize = firstRightList.size();

            // they are both size, simply addAll will work
            if (lastLeftSize + firstRightSize == 2 * size) {
                System.out.println("Perfect!");
                list.addAll(right.list);
                return this;
            }

            // last and first from each chunk are merged "perfectly"
            if (lastLeftSize + firstRightSize == size) {
                System.out.println("Almost perfect");
                int x = 0;
                while (x < firstRightSize) {
                    lastLeftList.add(firstRightList.remove(x));
                    --firstRightSize;
                }
                right.list.remove(0);
                list.addAll(right.list);
                return this;
            }

            right.list.stream().flatMap(List::stream).forEach(this::add);
            return this;
        }

        public String finisher() {
            return list.stream().map(x -> x.stream().collect(Collectors.joining(",")))
                    .collect(Collectors.collectingAndThen(Collectors.joining(",\n"), x -> x + "."));
        }

    }
    return Collector.of(Acc::new, Acc::add, Acc::merge, Acc::finisher);
}

使用方法是:

String result = IntStream.rangeClosed(0, 24)
            .mapToObj(String::valueOf)
            .collect(partitioning(10));