MST

星途 面试题库

面试题:Java Stream链式调用中的性能优化

在复杂的Java Stream链式调用场景下,比如有多个filter、map、sorted等操作,可能会出现性能问题。请分析可能导致性能问题的原因,并说明如何对这样的链式调用进行性能优化,至少列举两种优化方式,并结合代码示例说明。
20.7万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

可能导致性能问题的原因

  1. 中间操作过多:过多的中间操作(如filter、map、sorted等)会增加计算量和内存开销。每一个中间操作都会生成一个新的流对象,这些对象在处理过程中需要占用额外的内存。
  2. 无序操作与有序操作混合:如果在链式调用中既有无序操作(如filter、map)又有有序操作(如sorted),并且无序操作在有序操作之前,可能会导致不必要的重新排序。
  3. 数据量过大:当处理大量数据时,每个操作都需要处理大量元素,会导致性能下降。例如,在大数据集上进行sorted操作会消耗大量时间和内存。

优化方式及代码示例

  1. 减少中间操作:尽量合并或简化中间操作,避免不必要的操作。
    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);
        }
    }
    
  2. 避免无序操作后接有序操作:如果可能,将有序操作放在链式调用的最后。
    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);
        }
    }
    
  3. 使用并行流:对于大数据集,可以使用并行流来充分利用多核处理器的优势。但要注意并行流可能会带来线程安全等问题,需谨慎使用。
    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) + " 毫秒");
        }
    }