Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Java

Khác biệt giữa Stream và Collection trong Java 8

Collection là cấu trúc dữ liệu lưu trữ (in-memory data structure). Stream là pipeline xử lý dữ liệu (computation pipeline). Khác biệt bản chất: "Lưu trữ" vs "Xử lý".

Bảng so sánh

Tiêu chíCollectionStream
Mục đíchLưu trữ & thao tác dữ liệu (add, remove, get, iterate)Xử lý dữ liệu (filter, map, reduce, collect) – không lưu trữ
Packagejava.util.* (List, Set, Queue, Map...)java.util.stream.* (Stream, IntStream...)
EvaluationEager – tính toán ngay khi add/putLazy – intermediate ops không chạy cho đến terminal op
ModificationCó thể add/remove/clearKhông thể sửa đổi (read-only view)
IterationExternal iteration (client dùng for/iterator)Internal iteration (Stream quản lý loop)
ReusabilityDùng nhiều lầnChỉ dùng 1 lần (terminal op consume stream)
ParallelismKhó (phải tự manage thread)Dễ dàng: .parallelStream()
StorageChứa elementsKhông chứa elements – chỉ reference source

Ví dụ Collections

import java.util.*;

public class CollectionDemo {
    public static void main(String[] args) {
        List laptops = new ArrayList<>();
        laptops.add("HCL"); laptops.add("Apple"); laptops.add("Dell");
        
        // External iteration
        for (String s : laptops) System.out.println(s);
        
        // Sort (mutates original list)
        laptops.sort(Comparator.naturalOrder());
        System.out.println("Sorted: " + laptops);
    }
}

Ví dụ Streams

import java.util.*;
import java.util.stream.*;

public class StreamDemo {
    public static void main(String[] args) {
        List laptops = Arrays.asList("HCL", "Apple", "Dell", "HP", "Lenovo");
        
        // Internal iteration, lazy, không mutate original
        List filtered = laptops.stream()
            .filter(s -> s.length() <= 4)    // Intermediate (lazy)
            .map(String::toUpperCase)        // Intermediate (lazy)
            .sorted()                        // Intermediate (stateful, lazy)
            .collect(Collectors.toList());   // Terminal (eager) – trigger execution
        
        System.out.println("Original: " + laptops);      // Unchanged
        System.out.println("Filtered: " + filtered);     // [DELL, HP]
        
        // Parallel processing dễ dàng
        long count = laptops.parallelStream()
            .filter(s -> s.contains("L"))
            .count();
        System.out.println("Count with 'L': " + count);
    }
}

Quan hệ: Collection → Stream → Collection

Collection source = ...;
Stream stream = source.stream();        // Collection → Stream
List result = stream.collect(toList()); // Stream → Collection (terminal)

Stream không thay thế Collection. Chúng bổ sung nhau: Collection lưu trữ, Stream xử lý.

Khi nào dùng cái nào?

  • Collection: Cần lưu trữ, truy cập ngẫu nhiên (get(index)), add/remove thường xuyên, duyệt nhiều lần, thread-safe container (ConcurrentHashMap).
  • Stream: Xử lý dữ liệu once-through: filter/map/reduce, pipeline phức tạp, parallel processing, functional style, chuyển đổi dữ liệu (ETL), không cần lưu trung gian.

Lưu ý hiệu năng

  • Stream có overhead object creation (lambda, spliterator) – không dùng cho loop đơn giản, hot path.
  • Parallel stream chỉ nhanh khi: dataset lớn, CPU-intensive, stateless ops, đủ core.
  • Primitive streams (IntStream, LongStream, DoubleStream) tránh boxing/unboxing – nhanh hơn nhiều cho số.