小编bbK*_*ing的帖子

如何将 Collectors.collectingAndThen 与 Collectors.groupingBy 一起使用

以以下列表为例:

List<String> input = List.of("FOO", "FOO", "FOO", "FOO", "FOO", "BAR", "BAR", "BAZ", "BAZ", "BAZ", "DOO", "DOO"); 
Run Code Online (Sandbox Code Playgroud)

我需要获取每个元素的相对频率并将其格式化为字符串。为此,我使用了两个步骤,首先创建频率图,然后计算相对百分比和格式:

Map<String, Long> relativeFrequency =
        input.stream().collect(Collectors.groupingBy(Function.identity(),Collectors.counting()));

Map<String, String> relativeFrequency2 = relativeFrequency.entrySet().stream()
        .collect(Collectors.toMap(Map.Entry::getKey,
                entry -> String.format ( "%.02f%%", entry.getValue() * 100.  / input.size() )));

System.out.println(relativeFrequency2);
Run Code Online (Sandbox Code Playgroud)

并得到结果

{BAR=16.67%, DOO=16.67%, FOO=41.67%, BAZ=25.00%}
Run Code Online (Sandbox Code Playgroud)

我被告知要重构上述内容并使用Collectors.collectingAndThen一次性完成,但我似乎找不到正确的语法(编译错误Operator '*' cannot be applied to '<lambda parameter>', 'double')。有人可以帮助纠正以下内容以获得与上面相同的结果吗?

Map<String, String> relativeFrequency3 = 
input.stream().collect(Collectors.collectingAndThen(Collectors.groupingBy(Function.identity(), Collectors.counting(),
                total -> String.format ( "%.02f%%", total * 100.  / input.size() ))
));
Run Code Online (Sandbox Code Playgroud)

java java-stream

2
推荐指数
1
解决办法
2028
查看次数

使用流分组时将字符串分为多个组

我正在尝试做的事情的简化示例:

假设我有一个字符串列表,需要根据是否包含特定子字符串的条件将其分为 4 组。如果一个字符串包含Foo它应该属于该组FOO,如果它包含Bar它应该属于该组BAR,如果它包含两者它应该出现在两个组中。

List<String> strings = List.of("Foo", "FooBar", "FooBarBaz", "XXX");
Run Code Online (Sandbox Code Playgroud)

由于字符串被分组到第一个匹配组中,因此上述输入的简单方法无法按预期工作:

Map<String,List<String>> result1 =
strings.stream()
        .collect(Collectors.groupingBy(
                        str -> str.contains("Foo") ? "FOO" :
                                    str.contains("Bar") ? "BAR" :
                                            str.contains("Baz") ? "BAZ" : "DEFAULT"));
Run Code Online (Sandbox Code Playgroud)

结果1是

{FOO=[Foo, FooBar, FooBarBaz], DEFAULT=[XXX]}
Run Code Online (Sandbox Code Playgroud)

期望的结果应该是

{FOO=[Foo, FooBar, FooBarBaz], BAR=[FooBar, FooBarBaz], BAZ=[FooBarBaz], DEFAULT=[XXX]}
Run Code Online (Sandbox Code Playgroud)

经过一段时间的搜索,我找到了另一种方法,它接近我想要的结果,但不太完全

Map<String,List<String>> result2 =
List.of("Foo", "Bar", "Baz", "Default").stream()
        .flatMap(str -> strings.stream().filter(s -> s.contains(str)).map(s -> new String[]{str.toUpperCase(), s}))
        .collect(Collectors.groupingBy(arr -> arr[0], Collectors.mapping(arr -> arr[1], Collectors.toList())));

System.out.println(result2);
Run Code Online (Sandbox Code Playgroud)

结果2是

{BAR=[FooBar, …
Run Code Online (Sandbox Code Playgroud)

java hashmap java-stream groupingby

2
推荐指数
2
解决办法
613
查看次数

Java Stream - 收集器内的类型推断问题

我有一个与此堆栈溢出问题类似的用例,并尝试使用它而不将结果存储在 a 中List<List<String>>,而是调用stream()它。

List<List<String>>如果由于类型不匹配而没有将其分配给我,则会出现奇怪的编译时错误。要重现该问题,只需注释掉输出的分配即可。

问题是为什么会出现这个编译错误呢?以及如何修复它?

public static void main(String args[]) {
    List<String> input = Arrays.asList("RED", "RED", "BLUE", "BLUE", "BLUE", "BLUE", "RED", "RED");
    List<List<String>> output =  // if this line commented it doesn't compile
        input.stream()
            .collect(Collector.of(
                ArrayList::new,
                (accumulator, item) -> {
                    if (accumulator.isEmpty()) {
                        List<String> list = new ArrayList<>();
                        list.add(item);
                        accumulator.add(list);
                    } else {
                        List<String> last = accumulator.get(accumulator.size() - 1);
                        if (last.isEmpty() || last.get(0).equals(item)) {
                            last.add(item);
                        } else {
                            List<String> list = new ArrayList<>();
                            list.add(item); …
Run Code Online (Sandbox Code Playgroud)

java generics type-inference java-stream collectors

2
推荐指数
1
解决办法
142
查看次数

Java流:使用groupingBy而不是列表时如何映射到单个项目

给定一个订单类,例如:

@ToString
@AllArgsConstructor
@Getter
static class Order {
    long customerId;
    LocalDate orderDate;
}
Run Code Online (Sandbox Code Playgroud)

和订单列表:

List<Order> orderList = List.of(new Order(1, LocalDate.of(2020,Month.APRIL,21)),
                                new Order(1, LocalDate.of(2021,Month.APRIL,21)),
                                new Order(1, LocalDate.of(2022,Month.APRIL,21)),
                                new Order(2, LocalDate.of(2020,Month.APRIL,21)),
                                new Order(2, LocalDate.of(2021,Month.APRIL,21)),
                                new Order(3, LocalDate.of(2020,Month.APRIL,21)),
                                new Order(3, LocalDate.of(2022,Month.APRIL,21)),
                                new Order(4, LocalDate.of(2020,Month.APRIL,21)));
Run Code Online (Sandbox Code Playgroud)

我需要获得一份清单,customerId其中列出了最后一次orderDate超过 6 个月的情况。所以对于上面的例子[2,4]。我的想法是首先按 分组customerId,第二个地图到最后orderDate,第三个过滤那些超过 6 个月的地图。我陷入了如何将最近的订单映射到单个订单的第二步orderDate

第一步

Map<Long, List<Order>> grouped =
        orderList.stream()
                .collect(Collectors.groupingBy(Order::getCustomerId));
Run Code Online (Sandbox Code Playgroud)

第二步(卡在这里如何更改上述内容以仅获取一项作为值)

Map<Long, Order> grouped =
        orderList.stream()
                .collect(Collectors.groupingBy(Order::getCustomerId, ???));
Run Code Online (Sandbox Code Playgroud)

甚至更好

Map<Long, LocalDate> grouped =
        orderList.stream()
                .collect(Collectors.groupingBy(Order::getCustomerId, …
Run Code Online (Sandbox Code Playgroud)

java java-stream

1
推荐指数
1
解决办法
689
查看次数

Java流列表到索引映射

如何从字符串列表中获取映射,其中索引是键,字符串是值?

如果我有这样一个清单

List<String> list = List.of("foo","bar","baz","doo");
Run Code Online (Sandbox Code Playgroud)

我想要得到一个Map<Integer,String>喜欢

{0=foo, 1=bar, 2=baz, 3=doo}
Run Code Online (Sandbox Code Playgroud)

当我执行以下操作时出现错误

static Map<Integer,String> mapToIndex(List<String> list) {
    return IntStream.range(0, list.size())
            .collect(Collectors.toMap(Function.identity(), i -> list.get(i)));
}
Run Code Online (Sandbox Code Playgroud)

错误

所需类型:int 提供:Object

当我将其转换为 int 或 Integer 时

static Map<Integer,String> mapToIndex(List<String> list) {
    return IntStream.range(0, list.size())
            .collect(Collectors.toMap(Function.identity(), i -> list.get((Integer) i)));
}
Run Code Online (Sandbox Code Playgroud)

我明白了

'java.util.stream.IntStream' 中的 'collect(java.util.function.Supplier, java.util.function.ObjIntConsumer, java.util.function.BiConsumer<R,R>)' 无法应用于 '(java .util.stream.Collector<java.lang.Object,capture<?>,java.util.Map<java.lang.Object,java.lang.String>>)'

我缺少什么?

java java-stream

1
推荐指数
1
解决办法
672
查看次数