如何用Java 8 Stream按元素比较两个列表并优化代码?
更优雅的Java 8 Stream实现compareTriplets方法
这是一道算法任务:遍历两个列表a和b的对应元素,若a[i] > b[i]则Alice得1分;若a[i] < b[i]则Bob得1分;相等则双方不得分,最终返回包含Alice得分和Bob得分的列表[Alice得分, Bob得分]。
原始循环实现
public static List<Integer> compareTriplets(List<Integer> a, List<Integer> b) { int alice = 0; int bob = 0; for (int i = 0; i < a.size(); i++) { if (a.get(i) > b.get(i)) alice++; else if (a.get(i) < b.get(i)) bob++; } return Arrays.asList(alice, bob); }
你尝试的Stream实现
public static List<Integer> compareTriplets(List<Integer> a, List<Integer> b) { Integer[] result = {0, 0}; IntStream.range(0, Math.min(a.size(), b.size())) .map(i -> a.get(i).compareTo(b.get(i))) .forEach(i -> { if (i > 0) result[0]++; else if (i < 0) result[1]++; }); return Arrays.asList(result); }
更简洁优雅的Stream写法
写法一:分两次统计(高可读性)
这种写法逻辑直观、代码简洁,适合列表规模不大的场景:
public static List<Integer> compareTriplets(List<Integer> a, List<Integer> b) { int size = Math.min(a.size(), b.size()); int alice = (int) IntStream.range(0, size) .filter(i -> a.get(i) > b.get(i)) .count(); int bob = (int) IntStream.range(0, size) .filter(i -> a.get(i) < b.get(i)) .count(); return Arrays.asList(alice, bob); }
写法二:单次遍历归约(函数式风格)
通过reduce操作在单次遍历中完成得分统计,避免外部可变容器:
public static List<Integer> compareTriplets(List<Integer> a, List<Integer> b) { int[] scores = IntStream.range(0, Math.min(a.size(), b.size())) .map(i -> a.get(i).compareTo(b.get(i))) .reduce(new int[]{0, 0}, (acc, cmp) -> { if (cmp > 0) acc[0]++; else if (cmp < 0) acc[1]++; return acc; }, (acc1, acc2) -> { acc1[0] += acc2[0]; acc1[1] += acc2[1]; return acc1; }); return Arrays.asList(scores[0], scores[1]); }
写法三:自定义收集器(复用性更强)
用自定义收集器封装得分统计逻辑,后续如需调整规则可直接修改收集器:
public static List<Integer> compareTriplets(List<Integer> a, List<Integer> b) { return IntStream.range(0, Math.min(a.size(), b.size())) .map(i -> a.get(i).compareTo(b.get(i))) .collect(Collector.of( () -> new int[]{0, 0}, (acc, cmp) -> { if (cmp > 0) acc[0]++; else if (cmp < 0) acc[1]++; }, (acc1, acc2) -> { acc1[0] += acc2[0]; acc1[1] += acc2[1]; return acc1; }, acc -> Arrays.asList(acc[0], acc[1]) )); }
内容的提问来源于stack exchange,提问作者Denis
相关产品推荐
相关产品推荐

