标签: java-stream

如何将 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
查看次数

如何使用 Java 8 迭代 Map 以获得重复字符键的字符串

我有一个Map如下所示:

Map<Character, Integer> map = new LinkedHashMap<Character, Integer>();
    map.put('c', 5);
    map.put('f', 2);
    map.put('r', 1);
    map.put('D', 3);
Run Code Online (Sandbox Code Playgroud)

我需要获得输出:

cccccffrDDD
Run Code Online (Sandbox Code Playgroud)

我可以在正常过程中做到这一点,但我想在 Java 8 中做到这一点。你能分享一些如何实现这一点的提示吗?

java string hashmap java-8 java-stream

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

Java 流:限制不适用于 Random().ints().sorted()

我有以下代码:

new Random().ints()
            .map(i -> i / 2)
            .limit(100)
            .toArray()
Run Code Online (Sandbox Code Playgroud)

...并且它按预期工作。

但这不起作用:

new Random().ints()
            .sorted()
            .map(i -> i / 2)
            .limit(100)
            .toArray()
Run Code Online (Sandbox Code Playgroud)

它抛出:

Exception in thread "main" java.lang.IllegalArgumentException: Stream size exceeds max array size
Run Code Online (Sandbox Code Playgroud)

limit 不应该使流短路并帮助将其限制为 100 个元素吗?

java java-8 java-stream

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

Java Stream:类 com.java8.Student 无法转换为类 java.lang.Comparable

我Student使用 java 8 的自然排序方法迭代所有数据sorted()。迭代学生数据时,在 IDE 控制台中出现异常class com.java8.Student cannot be cast to class java.lang.Comparable。我的StreamStudent.java文件在com.java8包内。

这是我的完整堆栈跟踪:

Exception in thread "main" java.lang.ClassCastException: class com.java8.Student cannot be cast to class java.lang.Comparable (com.java8.Student is in unnamed module of loader 'app'; java.lang.Comparable is in module java.base of loader 'bootstrap')
    at java.base/java.util.Comparators$NaturalOrderComparator.compare(Comparators.java:47)
    at java.base/java.util.TimSort.countRunAndMakeAscending(TimSort.java:355)
    at java.base/java.util.TimSort.sort(TimSort.java:220)
    at java.base/java.util.Arrays.sort(Arrays.java:1307)
    at java.base/java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:353)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:510)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
    at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
    at com.java8.StreamStudent.main(StreamStudent.java:72)
Run Code Online (Sandbox Code Playgroud)

下面是我的代码:

package com.java8;

import java.util.*; …
Run Code Online (Sandbox Code Playgroud)

java comparable java-8 java-stream

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

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

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

假设我有一个字符串列表,需要根据是否包含特定子字符串的条件将其分为 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
查看次数

JDK8中可以只用一个流表达式来得到两个条件的结果吗?

这是我的代码,但我发现它不好。在JDK8中我可以只使用一个流表达式来获得两个条件的结果吗?我想确保id条件是第一个,名称条件是第二个。

  public Student getStudent(String id,String name)  {
    try {
        List<Student> students = studentDao.getStudent();
        if (CollectionUtils.isNotEmpty(students)) {
            Student studentDomain=students.stream()
                    .filter(p -> id .equals(p.getId()))
                    .findAny().orElse(null);
            if(studentDomain==null){
                studentDomain=students.stream()
                        .filter(p -> name.equals(p.getName()))
                        .findAny()
                        .orElse(null);
            }
            return studentDomain;
        } else {
            return null;
        }
    }catch (Exception ex){ 
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

java java-8 java-stream

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

根据两个List的内容生成SortedMap

我正在尝试直接从来自两个不同源的SortedMap两个流生成一个使用流。ArrayList我的目标是存储第二个列表中的SortedMap属性Double作为键,将第一个列表中的对象作为值(如果这些对象具有匹配的属性),该属性由辅助对象检查。

到目前为止,我可以使用以下方法完成它:

SortedMap<Double, FirstObject> myMap = new TreeMap<>(Double::compareTo);

List<FirstObject> myList = firstDao.get(someId).stream()
    .filter(firstobject -> secondDao.get(firstObject.getObjectId())
        .stream()
        .anyMatch(secondObject -> {
            if (Helper.check(secondObject).matches()) {
                myMap.put(
                    secondObject.getEfficiency(), firstObject
                );
            }
            return Helper.check(secondObject).matches();
    }))
    .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

我用该代码生成的代码没有用处myList,但到目前为止,这是我能够填充Map.

有没有一种方法可以直接填充到SortedMap而不需要生成该列表?

java arraylist treemap sortedmap java-stream

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

Reduce 无法推断正确的方法版本

我想让我的代码更通用。为了实现这一点,我证明了列表和供应商都是方法参数。

事实证明,reduce()在有多个可供选择的情况下,无法推断具体方法(见下面的屏幕截图)。

如何声明我想要使用的方法版本?

public BigDecimal methodCalculate(List<MyObject> list, Supplier<? extends BigDecimal> getValue) {
    BigDecimal sum = list.stream()
            .filter(item -> item.getPremium())
            .map(item -> getValue)
            .reduce(BigDecimal.ZERO, BigDecimal::add);
    return sum;
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

java java-stream supplier

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

使用 Java-Streams 从这些对象的两个字符串字段的不同字符串值列表的自定义对象列表中获取

自定义类对象中特定字段的 Java 流

我有一个ArrayList对象Train。

每个Train都有三个字段:source、destination、cost。

我想获取所有地名,即所有不同的来源+目的地。

我正在使用下面的代码,但正如可以观察到的那样,我使用两个流来检索数据。

List<String> destinations = list.stream()
    .map(x -> x.getDestination())
    .distinct()
    .collect(Collectors.toList());

List<String> sources = List.stream()
    .map(x -> x.getSource())
    .distinct()
    .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

我想知道如何在单个流中完成同样的事情?可以使用 来完成吗flatMap,还是有其他方法可以实现这一目标?

List<String> allPlaces = ?
Run Code Online (Sandbox Code Playgroud)

另外,是否可以使用Train没有吸气剂的类?

java java-stream flatmap

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

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
查看次数