我不太熟悉Java 8(仍在学习),并希望了解是否可以使用流找到与以下代码等效的东西。
下面的代码主要尝试为String中的每个值获取对应的double值,然后将其求和。在这种格式下,我找不到任何帮助。我不确定使用流是否会清理代码或使代码更混乱。
// safe assumptions - String/List (Key/Value) cannot be null or empty
// inputMap --> Map<String, List<String>>
Map<String, Double> finalResult = new HashMap<>();
for (Map.Entry<String, List<String>> entry : inputMap.entrySet()) {
Double score = 0.0;
for (String current: entry.getValue()) {
score += computeScore(current);
}
finalResult.put(entry.getKey(), score);
}
private Double computeScore(String a) { .. }
答案 0 :(得分:11)
Map<String, Double> finalResult = inputMap.entrySet()
.stream()
.collect(Collectors.toMap(
Entry::getKey,
e -> e.getValue()
.stream()
.mapToDouble(str -> computeScore(str))
.sum()));
上面的代码遍历整个地图,并使用相同的键创建一个新的地图;在放置值之前,它首先遍历每个值-这是一个列表,通过在每个列表元素上调用computeScore()
计算得分,然后对收集的分数求和,将其加到值中。
答案 1 :(得分:7)
您还可以将forEach
方法与流API结合使用以产生所需的结果。
Map<String, Double> resultSet = new HashMap<>();
inputMap.forEach((k, v) -> resultSet.put(k, v.stream()
.mapToDouble(s -> computeScore(s)).sum()));
s -> computeScore(s)
可以更改为使用方法引用,即T::computeScore
,其中T
是包含computeScore
的类的名称。
答案 2 :(得分:3)
这个怎么样?
=IFERROR(
IF(AND((LEFT($J2,3)="028"),$N2=11),
"NI Landline",
IF(AND((LEFT($J2,2)="07"),$N2=11),
"UK Mobile",
IF(AND((LEFT($J2,5)="00353"),$N2=14),
"ROI Number",
"Other Number")),
="Other Number")
以上版本可以合并为单个Map<String, Double> finalResult = inputMap.entrySet()
.stream()
.map(entry -> new AbstractMap.SimpleEntry<String, Double>( // maps each key to a new
// Entry<String, Double>
entry.getKey(), // the same key
entry.getValue().stream()
.mapToDouble(string -> computeScore(string)).sum())) // List<String> mapped to
// List<Double> and summed
.collect(Collectors.toMap(Entry::getKey, Entry::getValue)); // collected by the same
// key and a newly
// calulcated value
方法:
collect(..)
关键部分:
collect(..)
使用带有Collector
的特定策略对元素进行归约。 Map<String, Double> finalResult = inputMap.entrySet()
.stream()
.collect(Collectors.toMap(
Entry::getKey, // keeps the same key
entry -> entry.getValue()
.stream() // List<String> -> Stream<String>
// then Stream<String> -> Stream<Double>
.mapToDouble(string -> computeScore(string))
.sum())); // and summed
是Entry::getKey
的快捷方式。映射键的功能。entry -> entry.getKey
返回entry -> entry.getValue().stream()
mapToDouble(..)
返回DoubleStream。该操作具有一个汇总操作sum(..)
,该操作对元素进行求和-一起为Map创建一个新值。答案 3 :(得分:0)
无论您使用基于流的解决方案还是基于循环的解决方案,这都是有益的,并增加一些清晰度和结构以将内部循环提取到方法中:
private double computeScore(Collection<String> strings)
{
return strings.stream().mapToDouble(this::computeScore).sum();
}
当然,这也可以使用循环来实现,但这正是要点:现在可以在外部循环中或在地图条目流的值上调用此方法。
也可以将外部循环或流拉入方法。在下面的示例中,我对此进行了概括:映射键的类型无关紧要。值是List
还是Collection
实例也是如此。
作为当前接受的答案的替代方法,此处基于流的解决方案不会填充手动创建的新地图。而是使用Collector
。
(这与其他答案类似,但是我认为提取的computeScore
方法大大简化了嵌套流必需的否则难看的lambda)
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
public class ToStreamOrNotToStream
{
public static void main(String[] args)
{
ToStreamOrNotToStream t = new ToStreamOrNotToStream();
Map<String, List<String>> inputMap =
new LinkedHashMap<String, List<String>>();
inputMap.put("A", Arrays.asList("1.0", "2.0", "3.0"));
inputMap.put("B", Arrays.asList("2.0", "3.0", "4.0"));
inputMap.put("C", Arrays.asList("3.0", "4.0", "5.0"));
System.out.println("Result A: " + t.computeA(inputMap));
System.out.println("Result B: " + t.computeB(inputMap));
}
private <T> Map<T, Double> computeA(
Map<T, ? extends Collection<String>> inputMap)
{
Map<T, Double> finalResult = new HashMap<>();
for (Entry<T, ? extends Collection<String>> entry : inputMap.entrySet())
{
double score = computeScore(entry.getValue());
finalResult.put(entry.getKey(), score);
}
return finalResult;
}
private <T> Map<T, Double> computeB(
Map<T, ? extends Collection<String>> inputMap)
{
return inputMap.entrySet().stream().collect(
Collectors.toMap(Entry::getKey, e -> computeScore(e.getValue())));
}
private double computeScore(Collection<String> strings)
{
return strings.stream().mapToDouble(this::computeScore).sum();
}
private double computeScore(String a)
{
return Double.parseDouble(a);
}
}
答案 4 :(得分:0)
我发现它有点短:
value = startDates.entrySet().stream().mapToDouble(Entry::getValue).sum();