אוספים (List, Set, Map)
למה צריך אוספים?
מערכים ב-Java הם מוגבלים: אורך קבוע, חסרים פונקציות בסיסיות (הוספה, הסרה, חיפוש), קשה לעבוד איתם. אוספים (Collections) הם מחלקות שמציעות מבני נתונים גמישים יותר.
אוסף הוא אובייקט שמכיל כמה אובייקטים אחרים, ומספק פונקציות לניהול שלהם.
שלושה סוגי אוספים עיקריים
| ממשק | מטרה | מימוש נפוץ |
|---|---|---|
List |
רשימה מסודרת, מאפשר כפילויות | ArrayList, LinkedList |
Set |
אוסף ללא כפילויות | HashSet, TreeSet |
Map |
צמדי מפתח-ערך | HashMap, TreeMap |
ייבוא
import java.util.*;
או את המחלקות הספציפיות:
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
List - רשימה
ArrayList
המימוש הנפוץ ביותר של List. תחת המכסה זה מערך דינמי שמתרחב לבד.
List<String> names = new ArrayList<>();
names.add("אורי"); // הוספה
names.add("דוד");
names.add("רחל");
System.out.println(names); // [אורי, דוד, רחל]
פונקציות נפוצות
names.add("יוסי"); // הוסף בסוף
names.add(0, "מרים"); // הכנס למיקום
names.get(1); // ערך במיקום
names.set(1, "שרה"); // החלף ערך
names.remove(0); // הסר לפי אינדקס
names.remove("דוד"); // הסר לפי ערך
names.size(); // גודל
names.contains("אורי"); // בדיקת הכלה
names.indexOf("רחל"); // מיקום
names.isEmpty(); // ריקה?
names.clear(); // ניקוי
מעבר על List
for (String name : names) {
System.out.println(name);
}
// או עם אינדקס
for (int i = 0; i < names.size(); i++) {
System.out.println(i + ": " + names.get(i));
}
LinkedList
מימוש אחר של List - רשימה מקושרת. יעיל להוספות/הסרות באמצע, פחות יעיל לגישה לפי אינדקס.
List<Integer> list = new LinkedList<>();
list.add(1);
list.add(2);
list.add(3);
מתי להשתמש? בדרך כלל ArrayList טוב יותר. השתמשו
ב-LinkedList רק כשאתם עושים הרבה הוספות/הסרות באמצע הרשימה.
Set - קבוצה
Set לא מאפשר כפילויות. אם מוסיפים ערך שכבר קיים - הוא פשוט מתעלם.
HashSet
Set<String> unique = new HashSet<>();
unique.add("תפוח");
unique.add("בננה");
unique.add("תפוח"); // לא יתווסף שוב
System.out.println(unique.size()); // 2
System.out.println(unique.contains("בננה")); // true
TreeSet
שומר על הערכים ממוינים:
Set<Integer> sorted = new TreeSet<>();
sorted.add(5);
sorted.add(1);
sorted.add(3);
System.out.println(sorted); // [1, 3, 5]
חשוב: ל-Set אין סדר מובטח (ב-HashSet). אם חשוב לכם הסדר - השתמשו
ב-TreeSet או LinkedHashSet.
Map - מילון
Map שומר צמדי מפתח → ערך. זה המבנה הטוב ביותר כשצריך לחפש ערכים לפי
מזהה.
HashMap
Map<String, Integer> ages = new HashMap<>();
ages.put("אורי", 25);
ages.put("דוד", 30);
ages.put("רחל", 28);
int uriAge = ages.get("אורי"); // 25
פונקציות נפוצות
ages.put("יוסי", 40); // הוסף / עדכן
ages.get("דוד"); // קבל ערך
ages.remove("אורי"); // הסר
ages.containsKey("רחל"); // יש מפתח?
ages.containsValue(30); // יש ערך?
ages.size(); // מספר הצמדים
ages.isEmpty(); // ריק?
ages.keySet(); // כל המפתחות
ages.values(); // כל הערכים
ages.entrySet(); // כל הצמדים
מעבר על Map
// לפי מפתחות
for (String key : ages.keySet()) {
System.out.println(key + ": " + ages.get(key));
}
// לפי צמדי מפתח-ערך (יעיל יותר)
for (Map.Entry<String, Integer> entry : ages.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
TreeMap
Map שבו המפתחות שמורים ממוינים:
Map<String, Integer> sorted = new TreeMap<>();
sorted.put("גולן", 1);
sorted.put("אבי", 2);
sorted.put("בני", 3);
// סדר: אבי, בני, גולן
גנריקס (Generics)
שימו לב לתחביר <String>, <Integer> וכו'. זה נקרא
Generics - דרך לציין איזה טיפוס האוסף יכיל.
List<String> names = new ArrayList<>(); // רשימת מחרוזות
List<Integer> numbers = new ArrayList<>(); // רשימת מספרים
Map<String, Integer> ages = new HashMap<>();
חשוב: לא ניתן להשתמש בטיפוסים פרימיטיביים כאן. במקום int -
Integer, במקום double - Double.
דוגמה: ספירת מילים
import java.util.*;
public class WordCounter {
public static void main(String[] args) {
String text = "apple banana apple cherry banana apple";
String[] words = text.split(" ");
Map<String, Integer> counts = new HashMap<>();
for (String word : words) {
counts.put(word, counts.getOrDefault(word, 0) + 1);
}
for (Map.Entry<String, Integer> entry : counts.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
}
}
פלט:
apple: 3
banana: 2
cherry: 1
מערך מול List - מתי מה?
| מערך | List |
|---|---|
| אורך קבוע | גמיש |
| מהיר יותר | גמישות על חשבון ביצועים |
| טוב למבנה מוגדר מראש | טוב לאוסף שצומח דינמית |
| יש פרימיטיביים | רק אובייקטים |
בדרך כלל List יעדיף על מערך בקוד מודרני.
בדקו את עצמכם
נסו לענות לבד לפני שאתם פותחים את התשובה.
-
איזה אוסף לא מאפשר כפילויות?
הצגת התשובה
תשובה ג. Set שומר כל ערך פעם אחת בלבד.
-
למה כותבים
List<Integer>ולאList<int>?הצגת התשובה
תשובה ג. Generics ב-Java עובדים רק עם אובייקטים, לא עם טיפוסים פרימיטיביים.
-
באיזה אוסף מחפשים ערך לפי מפתח, כמו טלפון לפי שם?
הצגת התשובה
תשובה א. Map שומר זוגות של מפתח וערך, עם שליפה מהירה לפי מפתח.