以以下列表为例:
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) 我有一个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 中做到这一点。你能分享一些如何实现这一点的提示吗?
我有以下代码:
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 个元素吗?
我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) 我正在尝试做的事情的简化示例:
假设我有一个字符串列表,需要根据是否包含特定子字符串的条件将其分为 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) 这是我的代码,但我发现它不好。在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) 我正在尝试直接从来自两个不同源的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而不需要生成该列表?
我想让我的代码更通用。为了实现这一点,我证明了列表和供应商都是方法参数。
事实证明,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 流
我有一个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没有吸气剂的类?
我有一个与此堆栈溢出问题类似的用例,并尝试使用它而不将结果存储在 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 ×10
java-stream ×10
java-8 ×4
hashmap ×2
arraylist ×1
collectors ×1
comparable ×1
flatmap ×1
generics ×1
groupingby ×1
sortedmap ×1
string ×1
supplier ×1
treemap ×1