使用Java Streams统计和打印一个链中的唯一列表项

lig*_*ght 6 java functional-programming java-stream

我试图仅使用功能性的编程构造(流,收集器,lambda表达式)来实现这一点。

假设list是一个String[]

{"Apple", "Samsung", "LG", "Oppo", "Apple", "Huawei", "Oppo"}
Run Code Online (Sandbox Code Playgroud)

我想从此数组中打印出不同的品牌名称列表,并为其编号,即:

1. Apple
2. Huawei
3. LG
4. Oppo
5. Samsung
Run Code Online (Sandbox Code Playgroud)

我可以打印出独特的元素(排序):

Stream.of(list)
    .distinct()
    .sorted()
    .forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)

但这没有显示前面的计数器。我尝试过,Collectors.counting()但是那当然没有用。

FP专家有什么帮助吗?


编辑:我理解有关在带索引的流上进行迭代的其他一些问题。但是,我不能简单地做:

IntStream.range(0, list.length)
        .mapToObj(a -> (a+1) + ". " + list[a])
        .collect(Collectors.toList())
        .forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)

因为原始数组包含重复元素。在打印结果之前,可能还会有其他情况,map并且filter可能需要在流上执行。

Ole*_*.V. 3

在 Holger\xe2\x80\x99s 评论后编辑:如果你只想要数组中遇到的顺序不同的品牌,你需要做的就是省略排序操作。

\n\n
    String[] list = {"Apple", "Samsung", "LG", "Oppo", "Apple", "Huawei", "Oppo"};\n    Stream.of(list)\n            .distinct()\n            .forEach(System.out::println);\n
Run Code Online (Sandbox Code Playgroud)\n\n

输出是:

\n\n
\n
Apple\nSamsung\nLG\nOppo\nHuawei\n
Run Code Online (Sandbox Code Playgroud)\n
\n\n

正如 Holger 所说,如果流在操作之前遇到顺序(您的流具有),distinct则保持遇到顺序。distinct

\n\n
\n

我实际上需要前面的计数器(1.2.3.4.5.)。

\n
\n\n

我首选的方法是使用增强for循环而不使用 lambda:

\n\n
    int counter = 0;\n    for (String brand : new LinkedHashSet<>(Arrays.asList(list))) {\n        counter++;\n        System.out.println("" + counter + ". " + brand);\n    }\n
Run Code Online (Sandbox Code Playgroud)\n\n

输出是:

\n\n
\n
1. Apple\n2. Samsung\n3. LG\n4. Oppo\n5. Huawei\n
Run Code Online (Sandbox Code Playgroud)\n
\n\n

您的进一步评论:

\n\n
\n

我想知道什么是“理想的 FP”解决方案。

\n
\n\n

我\xe2\x80\x99m 不一定相信存在任何好的纯函数式编程解决方案。我的尝试是受到链接的原始问题及其答案的启发:

\n\n
    List<String> distinctBrands\n            = new ArrayList<>(new LinkedHashSet<>(Arrays.asList(list)));\n    IntStream.range(0, distinctBrands.size())\n            .mapToObj(index -> "" + (index + 1) + ". " + distinctBrands.get(index))\n            .forEach(System.out::println);\n
Run Code Online (Sandbox Code Playgroud)\n\n

ALinkedHashSet维护插入顺序并删除重复项。输出与之前相同。

\n

  • 如果流一开始就有遇到顺序,则流上的“distinct()”*确实*会维持顺序。但由于 OP 已将“.sorted()”链接在“.distinct()”之后,因此即使不是也没关系。一个有趣的事实是,当您在“.sorted()”之后链接“.distinct()”时,它不仅会维护顺序,还会利用元素已经排序的事实来进行廉价的不同操作。 (6认同)