บทนำ: ทำไมต้องมี Collections?
เมื่อเขียนโปรแกรม เราบ่อยครั้งต้องเก็บข้อมูล หลายตัว แต่ประเภทเดียวกัน เช่น:
- รายชื่อนักเรียน (หลายๆ คน)
- ราคาสินค้า (หลายๆ ราคา)
- ห้องพัก (หลายๆ ห้อง)
Array สามารถทำได้ แต่มีข้อจำกัด – ขนาดต้องกำหนดตั้งแต่แรก และ ถ้าต้อง insert หรือ delete ตรงกลาง ยุ่งยาก
Collections Framework คือ ชุดของ data structures (เหมือน “ตู้เก็บ”) ที่ Java มี built-in ให้ เพื่อเก็บข้อมูลได้ยืดหยุ่นกว่า
Collections Framework ที่สำคัญ:
├─ List → เก็บข้อมูลตามลำดับ (เหมือน queue คิวรอเข้า)
├─ Set → เก็บข้อมูลไม่ซ้ำกัน (เหมือน กลุ่ม ไม่มีสมาชิกซ้ำ)
├─ Map → เก็บคู่ key-value (เหมือนพจนานุกรม)
└─ Queue → ใหม่สำหรับ FIFO/LIFO (ลำดับเข้าก่อนออกก่อน)
- บทนำ: ทำไมต้องมี Collections?
- 1. List: เก็บข้อมูลตามลำดับ
- ความเข้าใจพื้นฐาน
- Implementation ของ List
- ตัวอย่างที่ 1: ArrayList ใช้งานพื้นฐาน
- ตัวอย่างที่ 2: List ของ Object
- 2. Set: เก็บข้อมูลไม่ซ้ำกัน
- ความเข้าใจพื้นฐาน
- Implementation ของ Set
- ตัวอย่างที่ 3: HashSet ใช้งานพื้นฐาน
- 3. Map: เก็บคู่ Key-Value
- ความเข้าใจพื้นฐาน
- Implementation ของ Map
- ตัวอย่างที่ 4: HashMap ใช้งานพื้นฐาน
- 4. Queue: FIFO (First In First Out)
- ความเข้าใจพื้นฐาน
- Implementation ของ Queue
- ตัวอย่างที่ 5: Queue ใช้งานพื้นฐาน
- ตัวอย่างรวม: ร้านค้า
- ตารางเปรียบเทียบ Collections
- สรุป
1. List: เก็บข้อมูลตามลำดับ
ความเข้าใจพื้นฐาน
List = คอลเล็กชันที่เก็บข้อมูลตามลำดับ (ordered) คุณสามารถ:
- เพิ่มข้อมูล
- ลบข้อมูล
- เข้าถึงข้อมูลด้วย index (ตำแหน่ง)
- ข้อมูลสามารถซ้ำกันได้
Implementation ของ List
textList (Interface)
├─ ArrayList ← ใช้งานบ่อยที่สุด (flexible, fast access)
├─ LinkedList ← ใช้เมื่อต้อง insert/delete บ่อย
└─ Vector ← เก่า (ไม่ใช้บ่อย)
ตัวอย่างที่ 1: ArrayList ใช้งานพื้นฐาน
javaimport java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
// ==== สร้าง ArrayList ====
List<String> students = new ArrayList<>();
// ==== เพิ่มข้อมูล (add) ====
students.add("สมชาย");
students.add("สมหญิง");
students.add("สมศรี");
students.add("สมชาย"); // ซ้ำกันได้
// ==== ขนาด (size) ====
System.out.println("จำนวนนักเรียน: " + students.size());
// ==== เข้าถึงข้อมูล (get) ====
System.out.println("นักเรียนคนที่ 1: " + students.get(0));
System.out.println("นักเรียนคนแรกสุด: " + students.get(students.size() - 1));
// ==== วนลูป ====
System.out.println("\n=== รายชื่อทั้งหมด ===");
for (String student : students) {
System.out.println("- " + student);
}
// ==== ลบข้อมูล (remove) ====
students.remove(1); // ลบตำแหน่งที่ 1 (สมหญิง)
System.out.println("\nหลังลบแล้ว: " + students);
// ==== แก้ไขข้อมูล (set) ====
students.set(0, "ชัยวัฒน์");
System.out.println("หลังแก้ไขแล้ว: " + students);
// ==== ตรวจสอบว่ามี (contains) ====
System.out.println("มี 'สมศรี' หรือไม่? " + students.contains("สมศรี"));
}
}
Output:
textจำนวนนักเรียน: 4
นักเรียนคนที่ 1: สมชาย
นักเรียนคนแรกสุด: สมชาย
=== รายชื่อทั้งหมด ===
- สมชาย
- สมหญิง
- สมศรี
- สมชาย
หลังลบแล้ว: [ชัยวัฒน์, สมศรี, สมชาย]
หลังแก้ไขแล้ว: [ชัยวัฒน์, สมศรี, สมชาย]
มี 'สมศรี' หรือไม่? true
คำอธิบาย:
ArrayList<String>= List ของ String.add()= เพิ่มข้อมูลท้ายสุด.get(index)= ได้ข้อมูลตำแหน่งที่ index.remove(index)= ลบข้อมูล.set(index, value)= แก้ไขข้อมูล.contains(value)= ตรวจสอบว่ามี
ตัวอย่างที่ 2: List ของ Object
javaimport java.util.ArrayList;
import java.util.List;
// ==== Class ====
public class Product {
private String name;
private double price;
public Product(String name, double price) {
this.name = name;
this.price = price;
}
@Override
public String toString() {
return name + " (" + price + " บาท)";
}
}
// ==== การใช้งาน ====
public class Main {
public static void main(String[] args) {
// สร้าง List ของ Product
List<Product> products = new ArrayList<>();
// เพิ่มสินค้า
products.add(new Product("Notebook", 50));
products.add(new Product("Pen", 10));
products.add(new Product("Pencil", 5));
// แสดงสินค้า
System.out.println("=== สินค้าทั้งหมด ===");
for (Product product : products) {
System.out.println("- " + product);
}
// คำนวณ total
double total = 0;
for (Product product : products) {
total += product.price; // ❌ error: price is private
}
}
}
หมายเหตุ: สำหรับ example นี้ คุณต้องทำให้ price เป็น public หรือสร้าง getter
2. Set: เก็บข้อมูลไม่ซ้ำกัน
ความเข้าใจพื้นฐาน
Set = คอลเล็กชันที่ไม่มีข้อมูลซ้ำกัน คุณสามารถ:
- เพิ่มข้อมูล
- ลบข้อมูล
- ตรวจสอบว่ามีข้อมูล
- ไม่สามารถเข้าถึงด้วย index ได้ (ไม่มี order)
Implementation ของ Set
textSet (Interface)
├─ HashSet ← ใช้งานบ่อยที่สุด (fast, unordered)
├─ LinkedHashSet ← เหมือน HashSet แต่ keep insertion order
└─ TreeSet ← ข้อมูล sorted
ตัวอย่างที่ 3: HashSet ใช้งานพื้นฐาน
javaimport java.util.HashSet;
import java.util.Set;
public class Main {
public static void main(String[] args) {
// ==== สร้าง HashSet ====
Set<String> fruits = new HashSet<>();
// ==== เพิ่มข้อมูล (add) ====
fruits.add("แอปเปิล");
fruits.add("กล้วย");
fruits.add("ส้ม");
fruits.add("แอปเปิล"); // ลองเพิ่มซ้ำ
// ==== ขนาด ====
System.out.println("จำนวนผลไม้: " + fruits.size());
// ❌ จะได้ 3 ไม่ใช่ 4 เพราะ "แอปเปิล" ซ้ำกัน
// ==== วนลูป ====
System.out.println("\n=== ผลไม้ทั้งหมด ===");
for (String fruit : fruits) {
System.out.println("- " + fruit);
}
// ⚠️ ลำดับอาจไม่ตามที่เพิ่ม (unordered)
// ==== ตรวจสอบ (contains) ====
System.out.println("\nมี 'กล้วย' หรือไม่? " + fruits.contains("กล้วย"));
System.out.println("มี 'องุ่น' หรือไม่? " + fruits.contains("องุ่น"));
// ==== ลบข้อมูล (remove) ====
fruits.remove("กล้วย");
System.out.println("\nหลังลบแล้ว: " + fruits);
// ==== ลบทั้งหมด (clear) ====
// fruits.clear();
// System.out.println("หลังลบหมด: " + fruits);
}
}
Output:
textจำนวนผลไม้: 3
=== ผลไม้ทั้งหมด ===
- ส้ม
- แอปเปิล
- กล้วย
มี 'กล้วย' หรือไม่? true
มี 'องุ่น' หรือไม่? false
หลังลบแล้ว: [ส้ม, แอปเปิล]
คำอธิบาย:
- Set ไม่รับข้อมูลซ้ำ – “แอปเปิล” ที่สองถูก ignore
.add()= เพิ่มข้อมูล.contains(value)= ตรวจสอบว่ามี.remove(value)= ลบข้อมูล- ไม่มี
.get(index)เพราะ Set ไม่มี order
3. Map: เก็บคู่ Key-Value
ความเข้าใจพื้นฐาน
Map = คอลเล็กชันที่เก็บคู่ key-value (เหมือนพจนานุกรม):
- ค้นหาข้อมูลด้วย key (ไม่ใช่ index)
- key ต้องไม่ซ้ำกัน (unique)
- value สามารถซ้ำกันได้
Implementation ของ Map
textMap (Interface)
├─ HashMap ← ใช้งานบ่อยที่สุด (fast lookup)
├─ LinkedHashMap ← keep insertion order
└─ TreeMap ← sorted by key
ตัวอย่างที่ 4: HashMap ใช้งานพื้นฐาน
javaimport java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
// ==== สร้าง HashMap ====
Map<String, Integer> scores = new HashMap<>();
// ==== เพิ่มข้อมูล (put) ====
scores.put("สมชาย", 85);
scores.put("สมหญิง", 90);
scores.put("สมศรี", 78);
// ==== ค้นหา (get) ====
System.out.println("คะแนน สมชาย: " + scores.get("สมชาย"));
System.out.println("คะแนน สมหญิง: " + scores.get("สมหญิง"));
// ==== จำนวน entry ====
System.out.println("จำนวน: " + scores.size());
// ==== วนลูป แบบ 1: keys ====
System.out.println("\n=== แบบ 1: วนลูป keys ===");
for (String key : scores.keySet()) {
System.out.println(key + " → " + scores.get(key));
}
// ==== วนลูป แบบ 2: values ====
System.out.println("\n=== แบบ 2: วนลูป values ===");
for (Integer value : scores.values()) {
System.out.println("คะแนน: " + value);
}
// ==== วนลูป แบบ 3: entry ====
System.out.println("\n=== แบบ 3: วนลูป entry ====");
for (Map.Entry<String, Integer> entry : scores.entrySet()) {
System.out.println(entry.getKey() + " ได้ " + entry.getValue());
}
// ==== ตรวจสอบ ====
System.out.println("\nมี 'สมศรี' หรือไม่? " + scores.containsKey("สมศรี"));
System.out.println("มีคะแนน 90 หรือไม่? " + scores.containsValue(90));
// ==== แก้ไขข้อมูล ====
scores.put("สมชาย", 95);
System.out.println("หลังแก้ไข: " + scores);
// ==== ลบข้อมูล ====
scores.remove("สมศรี");
System.out.println("หลังลบ: " + scores);
}
}
Output:
textคะแนน สมชาย: 85
คะแนน สมหญิง: 90
จำนวน: 3
=== แบบ 1: วนลูป keys ===
สมศรี → 78
สมชาย → 85
สมหญิง → 90
=== แบบ 2: วนลูป values ===
คะแนน: 78
คะแนน: 85
คะแนน: 90
=== แบบ 3: วนลูป entry ===
สมศรี ได้ 78
สมชาย ได้ 85
สมหญิง ได้ 90
มี 'สมศรี' หรือไม่? true
มีคะแนน 90 หรือไม่? true
หลังแก้ไข: {สมศรี=78, สมชาย=95, สมหญิง=90}
หลังลบ: {สมชาย=95, สมหญิง=90}
คำอธิบาย:
HashMap<String, Integer>= key เป็น String, value เป็น Integer.put(key, value)= เพิ่มคู่ key-value.get(key)= ค้นหา value ด้วย key.keySet()= ได้ทุก keys.values()= ได้ทุก values.entrySet()= ได้ทุก entry (key+value pairs)
4. Queue: FIFO (First In First Out)
ความเข้าใจพื้นฐาน
Queue = คิวของข้อมูล (เหมือนคิวรอเข้า):
- ข้อมูลที่เพิ่มเข้ามา ก่อนสุด จะ ออกมา ก่อนสุด (FIFO)
- เหมาะสำหรับ task scheduling, message queue
Implementation ของ Queue
textQueue (Interface)
├─ LinkedList ← ใช้งานบ่อยที่สุด (implement both Queue + List)
└─ PriorityQueue ← ข้อมูล sorted by priority
ตัวอย่างที่ 5: Queue ใช้งานพื้นฐาน
javaimport java.util.LinkedList;
import java.util.Queue;
public class Main {
public static void main(String[] args) {
// ==== สร้าง Queue ====
Queue<String> taskQueue = new LinkedList<>();
// ==== เพิ่มข้อมูล (offer / add) ====
taskQueue.offer("ทำการบ้าน");
taskQueue.offer("อ่านหนังสือ");
taskQueue.offer("เล่นเกม");
taskQueue.offer("นอน");
System.out.println("Queue: " + taskQueue);
// ==== ดู element หน้าสุด (peek) ====
System.out.println("\nTask หน้าสุด: " + taskQueue.peek());
System.out.println("Queue ยังคงเหมือนเดิม: " + taskQueue);
// ==== ดึงข้อมูลออก (poll) ====
System.out.println("\n=== ดำเนินการ task ===");
while (!taskQueue.isEmpty()) {
String task = taskQueue.poll();
System.out.println("✓ " + task);
}
System.out.println("\nQueue หลังจบ: " + taskQueue);
}
}
Output:
textQueue: [ทำการบ้าน, อ่านหนังสือ, เล่นเกม, นอน]
Task หน้าสุด: ทำการบ้าน
Queue ยังคงเหมือนเดิม: [ทำการบ้าน, อ่านหนังสือ, เล่นเกม, นอน]
=== ดำเนินการ task ===
✓ ทำการบ้าน
✓ อ่านหนังสือ
✓ เล่นเกม
✓ นอน
Queue หลังจบ: []
คำอธิบาย:
.offer(value)= เพิ่มข้อมูลท้ายสุด.poll()= ดึงข้อมูลหน้าสุดออก (FIFO).peek()= ดู element หน้าสุดโดยไม่ดึงออก.isEmpty()= ตรวจสอบว่าว่าง
ตัวอย่างรวม: ร้านค้า
javaimport java.util.*;
// ==== Product class ====
public class Product {
private String id;
private String name;
private double price;
public Product(String id, String name, double price) {
this.id = id;
this.name = name;
this.price = price;
}
public String getId() { return id; }
public String getName() { return name; }
public double getPrice() { return price; }
@Override
public String toString() {
return name + " (" + price + " บาท)";
}
}
// ==== การใช้ Collections ====
public class Store {
private List<Product> inventory; // List: สินค้าทั้งหมด
private Set<String> soldCategories; // Set: หมวดหมู่ที่ขายแล้ว
private Map<String, Integer> stock; // Map: ราคา key = ID, value = จำนวน
private Queue<String> orders; // Queue: คิวคำสั่งซื้อ
public Store() {
this.inventory = new ArrayList<>();
this.soldCategories = new HashSet<>();
this.stock = new HashMap<>();
this.orders = new LinkedList<>();
}
public void addProduct(Product product, int quantity) {
inventory.add(product);
stock.put(product.getId(), quantity);
}
public void sell(String productID) {
if (stock.containsKey(productID)) {
int qty = stock.get(productID);
if (qty > 0) {
stock.put(productID, qty - 1);
soldCategories.add(productID);
orders.offer(productID);
System.out.println("✓ ขายสินค้า ID: " + productID);
}
}
}
public void processOrders() {
System.out.println("\n=== ประมวลผลคำสั่งซื้อ ===");
while (!orders.isEmpty()) {
String orderedID = orders.poll();
System.out.println("- ส่งสินค้า ID: " + orderedID);
}
}
public void showStatus() {
System.out.println("\n=== สถานะร้านค้า ===");
System.out.println("สินค้าทั้งหมด: " + inventory.size());
System.out.println("หมวดหมู่ที่ขายแล้ว: " + soldCategories);
System.out.println("จำนวนคงคลัง: " + stock);
}
}
// ==== Main ====
public class Main {
public static void main(String[] args) {
Store store = new Store();
// เพิ่มสินค้า
store.addProduct(new Product("P001", "Notebook", 50), 10);
store.addProduct(new Product("P002", "Pen", 10), 20);
store.addProduct(new Product("P003", "Pencil", 5), 15);
store.showStatus();
// ขายสินค้า
store.sell("P001");
store.sell("P002");
store.sell("P001");
store.sell("P003");
store.processOrders();
store.showStatus();
}
}
Output:
text=== สถานะร้านค้า ===
สินค้าทั้งหมด: 3
หมวดหมู่ที่ขายแล้ว: []
จำนวนคงคลัง: {P001=10, P002=20, P003=15}
✓ ขายสินค้า ID: P001
✓ ขายสินค้า ID: P002
✓ ขายสินค้า ID: P001
✓ ขายสินค้า ID: P003
=== ประมวลผลคำสั่งซื้อ ===
- ส่งสินค้า ID: P001
- ส่งสินค้า ID: P002
- ส่งสินค้า ID: P001
- ส่งสินค้า ID: P003
=== สถานะร้านค้า ===
สินค้าทั้งหมด: 3
หมวดหมู่ที่ขายแล้ว: [P001, P002, P003]
จำนวนคงคลัง: {P001=8, P002=19, P003=14}
ตารางเปรียบเทียบ Collections
| Collection | ลักษณะ | ใช้เมื่อไร | ตัวอย่าง |
|---|---|---|---|
| List | Ordered, ซ้ำได้ | ต้อง access ตามลำดับ, ต้อง index | รายชื่อนักเรียน |
| Set | ไม่ซ้ำ, unordered | ต้องไม่ซ้ำ, ไม่สนใจลำดับ | หมวดหมู่, category |
| Map | Key-value pairs | ต้องค้นหาด้วย key | ราคาสินค้า, พจนานุกรม |
| Queue | FIFO | ต้องลำดับเข้าก่อนออกก่อน | task scheduler |
สรุป
Collections Framework คือชุดของ data structures ที่ Java มีให้ใช้สำหรับเก็บข้อมูลหลายตัวอย่างยืดหยุ่น:
- List – ใช้เมื่อต้อง เก็บข้อมูลตามลำดับ และ เข้าถึงด้วย index
- Set – ใช้เมื่อต้อง ไม่ให้ข้อมูลซ้ำ และ ไม่สนใจลำดับ
- Map – ใช้เมื่อต้อง ค้นหาข้อมูลด้วย key (เหมือนพจนานุกรม)
- Queue – ใช้เมื่อต้อง ลำดับ FIFO (ทำให้เข้ามาก่อนออกมาก่อน)
การเลือกใช้ collection ที่เหมาะสม จะทำให้ code มีประสิทธิภาพ อ่านเข้าใจง่าย และดูแลรักษาได้ดี
