面试题答案
一键面试可能导致性能问题的原因
- 中间操作过多:过多的中间操作(如filter、map、sorted等)会增加计算量和内存开销。每一个中间操作都会生成一个新的流对象,这些对象在处理过程中需要占用额外的内存。
- 无序操作与有序操作混合:如果在链式调用中既有无序操作(如filter、map)又有有序操作(如sorted),并且无序操作在有序操作之前,可能会导致不必要的重新排序。
- 数据量过大:当处理大量数据时,每个操作都需要处理大量元素,会导致性能下降。例如,在大数据集上进行sorted操作会消耗大量时间和内存。
优化方式及代码示例
- 减少中间操作:尽量合并或简化中间操作,避免不必要的操作。
import java.util.Arrays; import java.util.List; public class StreamOptimization { public static void main(String[] args) { List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // 优化前 int sum1 = numbers.stream() .filter(n -> n % 2 == 0) .map(n -> n * 2) .filter(n -> n > 5) .mapToInt(Integer::intValue) .sum(); // 优化后 int sum2 = numbers.stream() .filter(n -> n % 2 == 0 && n * 2 > 5) .mapToInt(n -> n * 2) .sum(); System.out.println("优化前的和: " + sum1); System.out.println("优化后的和: " + sum2); } }
- 避免无序操作后接有序操作:如果可能,将有序操作放在链式调用的最后。
import java.util.Arrays; import java.util.List; public class StreamOptimization2 { public static void main(String[] args) { List<Integer> numbers = Arrays.asList(3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5); // 优化前(无序操作后接有序操作) numbers.stream() .map(n -> n * 2) .sorted() .forEach(System.out::println); // 优化后(有序操作放在最后) numbers.stream() .sorted() .map(n -> n * 2) .forEach(System.out::println); } }
- 使用并行流:对于大数据集,可以使用并行流来充分利用多核处理器的优势。但要注意并行流可能会带来线程安全等问题,需谨慎使用。
import java.util.Arrays; import java.util.List; public class StreamOptimization3 { public static void main(String[] args) { List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); // 顺序流 long startTime1 = System.currentTimeMillis(); int sum1 = numbers.stream() .filter(n -> n % 2 == 0) .mapToInt(Integer::intValue) .sum(); long endTime1 = System.currentTimeMillis(); // 并行流 long startTime2 = System.currentTimeMillis(); int sum2 = numbers.parallelStream() .filter(n -> n % 2 == 0) .mapToInt(Integer::intValue) .sum(); long endTime2 = System.currentTimeMillis(); System.out.println("顺序流求和: " + sum1 + ",耗时: " + (endTime1 - startTime1) + " 毫秒"); System.out.println("并行流求和: " + sum2 + ",耗时: " + (endTime2 - startTime2) + " 毫秒"); } }