最近,我偶然发现了一个有趣的Stream挑战,有一个要求是创建一个Java (8)流,从输入文件中读取整数并生成一个映射,将数字映射到相应的最小质因数。.
到目前为止,我的看法是:如果没有合并BiFunction,我会得到重复的键异常,所以我做了上面的工作,它用分号连接类似的映射值。
Map<Integer, String> map = Files.lines(Path.of("nums.txt")).filter(s -> Integer.parseInt(s) > 2).map(Integer::parseInt)
.collect(Collectors.toMap(i -> {
if(i == 2) return 2;
var divisors = IntStream.rangeClosed(2, i).filter(j -> i % j== 0).boxed()
.collect(Collectors.toList());
return divisors.stream().filter(integer -> {
for(int ii = 2; ii < Math.sqrt(integer); ii++) {
if(integer % ii == 0) return false;
}
return true;
}).findFirst().orElse(-1);
}, String::valueOf
, (s1, s2) -> s1 + ";" + s2));
现在如果没有合并BiFunction,我就会得到重复的键异常,所以为了避免这种情况,我做了上面的变通方法,它用分号将类似的映射值连接起来。
我发现这个解决方案有点蹩脚,但是,我想知道,我的映射是否可以有一个 "分号"。设置实现的第二个类型参数,并将类似的映射值收集到一个集合中。
主要的问题是,如果我在KeyMapper函数中实例化了新的HashMap,它总是会为每个重复的键返回一个新的键,因此两个HashSets的合并尝试 徒劳无功.
P.s.关于流本身的反馈也是好评如潮,我不知道这种方法是否是不必要的复杂。
不幸的是,这样的问题是可以解释的。 例如,如果做了这样的事情呢?
String file = "<number file>";
try {
Map<Integer, List<Integer>> factors = new HashMap<>();
Files.lines(Path.of(file)).map(Integer::parseInt).forEach(n-> {
//code here to fill the map factors
});
} catch (IOException ie) {
ie.printStackTrace();
}
或者像这样
String file = "<number file>";
try {
Map<Integer, List<Integer>> factors =
Files.lines(Path.of(file)).map(Integer::parseInt)
.collect(Collectors.toMap(i -> i,
i -> primeFactors(i)));
} catch (IOException ie) {
ie.printStackTrace();
}
public static List<Integer> primeFactors(int i) {
List<Integer> factors = new ArrayList<>();
// code here to find the factors
return factors;
}
有几种先进的算法存在于复合数的因数中。 这些算法不一定适合于 stream
加工;