nik*_*abu 5 java-8 java-stream
我是Streams的新手Java 8,目前正在尝试解决这个问题,我有两个列表如下:
List<Integer> list1 = Arrays.asList(5, 11,17,123);
List<Integer> list2 = Arrays.asList(124,14,80);
Run Code Online (Sandbox Code Playgroud)
我想找到这些列表中所有元素之间存在的绝对最小差异.
预期结果: 1(124-123=1)
使用Java 7实现它不是问题,但我如何使用Java8的Streams实现它?我如何迭代forEach元素List1,也forEach来自List2和保持最小值?
试试这个吧
public static void main(String[] args) {
List<Integer> list1 = Arrays.asList(5, 11,17,123);
List<Integer> list2 = Arrays.asList(124,14,80);
OptionalInt min = list1.stream()
.flatMap(n -> list2.stream()
.map(r -> n-r > 0? n-r: r-n))
.mapToInt(t -> t).min();
System.out.println(min.getAsInt());
}
Run Code Online (Sandbox Code Playgroud)
编辑(Holger建议)
OptionalLong min = list1.stream()
.flatMapToLong(n -> list2.stream()
.mapToLong(r -> Math.abs(r-(long)n))).min();
Run Code Online (Sandbox Code Playgroud)
虽然很容易将"将list1的每个元素与list2的每个元素进行比较"逻辑转换为使用Stream API的代码,并且解决方案的源代码可能很短,但它不是一个有效的解决方案.如果列表相当大,您将最终执行n×m次操作.
此外,请注意两个int值之间的距离最大可达2³,这不符合(带符号)int值范围.long如果您正在寻找一般解决方案,那么您应该用它来表达结果.
所以解决方案可能如下所示:
public static long smallestDistance(List<Integer> list1, List<Integer> list2) {
int[] list2Sorted = list2.stream().mapToInt(Integer::intValue).sorted().toArray();
if(list2Sorted.length == 0) throw new IllegalArgumentException("list2 is empty");
long smallest = Long.MAX_VALUE;
for(int i: list1) {
int pos = Arrays.binarySearch(list2Sorted, i);
if(pos >= 0) return 0;
pos ^= -1;
if(pos < list2Sorted.length) {
long d = Math.abs(list2Sorted[pos] - (long)i);
if(d < smallest) smallest = d;
}
if(pos > 0) {
long d = Math.abs(list2Sorted[pos-1] - (long)i);
if(d < smallest) smallest = d;
}
}
if(smallest == Long.MAX_VALUE) throw new IllegalArgumentException("list1 is empty");
return smallest;
}
Run Code Online (Sandbox Code Playgroud)
通过对一个列表进行排序,我们可以有效地查找其他列表中每个元素的最接近元素.这样,时间复杂度从O(n×m)(所有情况)减少到O((n+m)×log(m))(最坏情况).作为奖励,如果发现匹配,它将立即返回,因为这意味着可能的最小距离为零.
如果要测试它,请考虑示例输入,如偶数列表和奇数列表:
List<Integer> list1
= IntStream.range(0, 100000).mapToObj(i -> i*2).collect(Collectors.toList());
List<Integer> list2
= IntStream.range(0, 100000).mapToObj(i -> i*2+1).collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
由于没有完全匹配,因此不可能进行短切,但不同的时间复杂度将变得明显.
| 归档时间: |
|
| 查看次数: |
969 次 |
| 最近记录: |