Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Java

ความแตกต่างระหว่าง Iterator และ Spliterator ใน Java

ทั้งคู่ใช้สำหรับ **iterate collections** แต่ Spliterator (Java 8+) ออกแบบมาสำหรับ **Parallel Processing** และ **Streams**

ตารางเปรียบเทียบ

ลำดับหัวข้อIteratorSpliterator
1พื้นฐานSequential traversal เท่านั้นSequential + **Parallel** traversal
2Packagejava.util.Iteratorjava.util.Spliterator
3Bulk Operationsไม่รองรับ (ต้อง loop เอง)รองรับ forEachRemaining(), trySplit()
4Iteration TypeExternal Iterator (client ควบคุม loop)Internal Iterator (Spliterator ควบคุม เอง)
5Splittingไม่สามารถ split ได้trySplit() แยกเป็นส่วนๆ สำหรับ parallel
6Size Estimationไม่มีestimateSize(), getExactSizeIfKnown()
7Characteristicsไม่มีมี characteristics (ORDERED, SORTED, DISTINCT, SIZED, ...)
8Stream Integrationไม่ใช่ (แต่ Collection.iterator() ใช้ได้)**Core ของ Stream API** - collection.spliterator()

Iterator - External Iteration

List list = Arrays.asList("A", "B", "C", "D");

// Client ควบคุมการ loop
Iterator it = list.iterator();
while (it.hasNext()) {
    String element = it.next();
    System.out.println(element);
}

// หรือ for-each (syntax sugar)
for (String s : list) {
    System.out.println(s);
}

Spliterator - Internal Iteration + Splitting

Methods หลัก

  • boolean tryAdvance(Consumer<T> action) - ประมวลผล 1 element (เหมือน hasNext+next)
  • void forEachRemaining(Consumer<T> action) - ประมวลผลทุก element ที่เหลือ
  • Spliterator<T> trySplit() - **พยายามแยก** ส่วนหนึ่งออกไป (สำหรับ parallel)
  • long estimateSize() - ประมาณจำนวน elements
  • int characteristics() - ลักษณะ (ORDERED, SORTED, DISTINCT, SIZED, SUBSIZED, NONNULL, IMMUTABLE, CONCURRENT)

ตัวอย่าง Spliterator พื้นฐาน

import java.util.*;
import java.util.Spliterator;

public class SpliteratorExample {
    public static void main(String[] args) {
        List list = Arrays.asList(78, 10, 20, 30, 40, 50, 60, 70);
        
        Spliterator spliterator = list.spliterator();
        System.out.println("Characteristics: " + spliterator.characteristics());
        System.out.println("Estimated size: " + spliterator.estimateSize());
        System.out.println("Exact size known: " + spliterator.getExactSizeIfKnown());
        
        // Split ลองแยกครึ่ง
        Spliterator split = spliterator.trySplit();
        System.out.println("\nOriginal (remaining):");
        spliterator.forEachRemaining(System.out::println);
        
        System.out.println("\nSplit part:");
        split.forEachRemaining(System.out::println);
    }
}

Output

Characteristics: 16464 (ORDERED | SIZED | SUBSIZED | DISTINCT | IMMUTABLE)
Estimated size: 8
Exact size known: 8

Original (remaining):
50
60
70
40

Split part:
10
20
30
78

Spliterator และ Parallel Streams

Stream ใช้ Spliterator ภายในเพื่อ parallel processing:

List numbers = IntStream.rangeClosed(1, 1_000_000).boxed().toList();

// Sequential - ใช้ 1 thread
long sumSeq = numbers.stream().mapToLong(Long::valueOf).sum();

// Parallel - Spliterator แยกงานให้หลาย threads
long sumPar = numbers.parallelStream().mapToLong(Long::valueOf).sum();

// Spliterator characteristics ช่วย optimize:
// - SIZED: รู้ขนาดแน่นอน → divide ง่าย
// - SUBSIZED: split parts ก็รู้ขนาด → divide ต่อได้
// - ORDERED: ต้องรักษาลำดับ → restrict parallelism บ้าง
// - DISTINCT: ไม่มี duplicate → optimize distinct()

Custom Spliterator (Advanced)

// Spliterator สำหรับ generate Fibonacci numbers (Infinite)
public class FibonacciSpliterator implements Spliterator {
    private long prev = 0, next = 1;
    private long count = 0;
    private final long maxCount;
    
    public FibonacciSpliterator(long maxCount) {
        this.maxCount = maxCount;
        this.characteristics = Spliterator.ORDERED | Spliterator.NONNULL | Spliterator.IMMUTABLE;
    }
    
    @Override
    public boolean tryAdvance(Consumer action) {
        if (count >= maxCount) return false;
        action.accept(prev);
        long temp = prev + next;
        prev = next;
        next = temp;
        count++;
        return true;
    }
    
    @Override
    public Spliterator trySplit() {
        // Fibonacci ไม่สะดวก split (stateful) - return null
        return null;
    }
    
    @Override
    public long estimateSize() {
        return maxCount - count;
    }
    
    @Override
    public int characteristics() {
        return characteristics;
    }
    
    // ใช้กับ Stream
    Stream fibStream = StreamSupport.stream(new FibonacciSpliterator(100), false);

สรุป: เมื่อไหร่ใช้อะไร?

สถานการณ์ใช้เหตุผล
Simple loop, for-eachIterator / for-eachเข้าใจง่าย, พอเพียง
ต้อง remove() ระหว่าง loopIteratorมี remove() method
Parallel processing, StreamsSpliteratorCore ของ parallel streams
Custom data structure ต้องการ parallelCustom SpliteratorImplement trySplit() ให้ถูกต้อง
Batch processing ทั้งชุดSpliterator.forEachRemaining()Internal iteration, optimized