Java存儲數(shù)據(jù)之數(shù)組與集合的詳細操作
Java存儲數(shù)據(jù):數(shù)組與集合
一、數(shù)組(Array)
1. 邏輯特征
- 固定大小:創(chuàng)建時指定長度,不能動態(tài)改變
- 類型統(tǒng)一:所有元素必須是相同數(shù)據(jù)類型
- 內(nèi)存連續(xù):元素在內(nèi)存中連續(xù)存儲
- 效率高:通過索引直接訪問,時間復雜度O(1)
- 功能簡單:提供基本的存儲和訪問能力
2. 代碼層面
// 1. 聲明和初始化
int[] numbers = new int[5]; // 長度為5的整型數(shù)組
String[] names = {"張三", "李四", "王五"};
// 2. 訪問和修改
numbers[0] = 10;
System.out.println(numbers[0]); // 輸出: 10
// 3. 遍歷數(shù)組
for (int i = 0; i < numbers.length; i++) {
System.out.println(numbers[i]);
}
// 4. 增強for循環(huán)
for (int num : numbers) {
System.out.println(num);
}
// 5. 多維數(shù)組
int[][] matrix = new int[3][3];
matrix[0][0] = 1;3. 數(shù)組的局限性
// 問題1: 數(shù)組大小固定,無法動態(tài)擴展 int[] arr = new int[3]; // arr[3] = 4; // ArrayIndexOutOfBoundsException // 問題2: 只能存儲同一類型數(shù)據(jù) // arr[0] = "hello"; // 編譯錯誤 // 問題3: 缺少高級操作方法 // 沒有內(nèi)置的add(), remove(), contains()等方法
二、為什么需要集合(Collection)
1. 數(shù)組的不足
- 大小固定:不能動態(tài)增長或收縮
- 功能有限:缺少增刪改查的高級方法
- 類型限制:只能存儲相同類型
- 代碼繁瑣:需要手動處理很多邏輯
2. 集合的優(yōu)勢
- 動態(tài)擴容:自動調(diào)整大小
- 功能豐富:提供各種操作方法
- 類型靈活:通過泛型支持類型安全
- 算法支持:內(nèi)置排序、查找等算法
三、集合知識體系
Java集合框架 (Java Collections Framework)
│
├── Collection接口 (單列集合)
│ ├── List接口 (有序、可重復)
│ │ ├── ArrayList: 數(shù)組實現(xiàn),查詢快,增刪慢
│ │ ├── LinkedList: 鏈表實現(xiàn),增刪快,查詢慢
│ │ └── Vector: 線程安全的ArrayList(已過時)
│ │
│ ├── Set接口 (無序、不可重復)
│ │ ├── HashSet: 哈希表實現(xiàn)
│ │ ├── LinkedHashSet: 有序的HashSet
│ │ └── TreeSet: 紅黑樹實現(xiàn),可排序
│ │
│ └── Queue接口 (隊列)
│ ├── LinkedList: 也實現(xiàn)了Queue
│ ├── PriorityQueue: 優(yōu)先級隊列
│ └── ArrayDeque: 雙端隊列
│
└── Map接口 (雙列集合,鍵值對)
├── HashMap: 最常用的Map
├── LinkedHashMap: 有序的HashMap
├── TreeMap: 可排序的Map
└── Hashtable: 線程安全的Map(已過時)四、主要集合類示例
1. ArrayList(最常用)
// 創(chuàng)建ArrayList
List<String> list = new ArrayList<>();
// 添加元素(自動擴容)
list.add("Java");
list.add("Python");
list.add("C++");
// 獲取元素
String first = list.get(0);
// 修改元素
list.set(1, "JavaScript");
// 刪除元素
list.remove(2);
// 遍歷
for (String language : list) {
System.out.println(language);
}
// 其他常用方法
int size = list.size(); // 大小
boolean empty = list.isEmpty(); // 是否為空
boolean contains = list.contains("Java"); // 是否包含2. LinkedList
// 創(chuàng)建LinkedList LinkedList<Integer> linkedList = new LinkedList<>(); // 添加元素 linkedList.add(10); linkedList.addFirst(5); // 頭部添加 linkedList.addLast(20); // 尾部添加 // 作為隊列使用 linkedList.offer(30); // 入隊 int head = linkedList.poll(); // 出隊 // 作為棧使用 linkedList.push(40); // 壓棧 int top = linkedList.pop(); // 彈棧
3. HashSet
// 創(chuàng)建HashSet
Set<String> set = new HashSet<>();
// 添加元素
set.add("Apple");
set.add("Banana");
set.add("Apple"); // 重復,不會添加
// 遍歷(無序)
for (String fruit : set) {
System.out.println(fruit);
}
// 常用操作
set.remove("Banana");
boolean hasApple = set.contains("Apple");4. HashMap
// 創(chuàng)建HashMap
Map<String, Integer> map = new HashMap<>();
// 添加鍵值對
map.put("Alice", 25);
map.put("Bob", 30);
map.put("Charlie", 28);
// 獲取值
int age = map.get("Alice");
// 遍歷
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
// 鍵集合和值集合
Set<String> keys = map.keySet();
Collection<Integer> values = map.values();
五、集合與數(shù)組的對比
| 特性 | 數(shù)組 | 集合 |
|---|---|---|
| 大小 | 固定,聲明時確定 | 動態(tài),可自動擴容 |
| 類型 | 必須統(tǒng)一 | 通過泛型支持多種類型 |
| 性能 | 訪問快(O(1)) | 實現(xiàn)不同,性能各異 |
| 功能 | 基本操作 | 豐富的高級操作 |
| 存儲 | 基本類型和對象 | 只能存儲對象 |
| 線程安全 | 不安全 | 大部分不安全 |
六、最佳實踐建議
- 優(yōu)先使用集合:除非對性能有極致要求,否則優(yōu)先使用集合
- 選擇合適的集合:
- 需要頻繁查詢 → ArrayList
- 需要頻繁增刪 → LinkedList
- 需要去重 → HashSet
- 需要鍵值對 → HashMap
- 使用泛型:確保類型安全
- 考慮線程安全:多線程環(huán)境使用ConcurrentHashMap、CopyOnWriteArrayList
- 初始化大小:如果知道大概數(shù)據(jù)量,可以指定初始容量
// 指定初始容量 List<String> list = new ArrayList<>(1000); Map<String, Integer> map = new HashMap<>(500);
七、總結(jié)
- 數(shù)組是Java語言的基礎數(shù)據(jù)結(jié)構(gòu),簡單高效但功能有限
- 集合是對數(shù)組的封裝和擴展,提供了更強大、更靈活的數(shù)據(jù)管理能力
- 現(xiàn)代Java開發(fā)中,集合是首選,數(shù)組主要用于:
- 性能敏感的場景
- 處理基本數(shù)據(jù)類型
- 與遺留代碼或API交互
- 理解不同集合的特性,根據(jù)需求選擇最合適的工具
實際開發(fā)中,ArrayList和HashMap是最常用的集合類,掌握了它們就解決了80%的數(shù)據(jù)存儲問題。
好的,專門說說遍歷集合!這是天天要用的操作,分幾種情況給你講清楚。
List遍歷(最常用)
1.普通for循環(huán)(有索引時用)
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
for (int i = 0; i < list.size(); i++) {
String item = list.get(i);
System.out.println(item);
}優(yōu)點:能拿到索引,方便操作
缺點:只有 ArrayList 這種基于數(shù)組的用著快,LinkedList 用這個就慢(因為要一個個數(shù)過去)
2.增強for循環(huán)(最常用、最簡潔)
for (String item : list) {
System.out.println(item);
}
優(yōu)點:寫法簡單,可讀性好
缺點:遍歷時不能修改集合(刪除、新增會拋異常)
3.迭代器Iterator(可以在遍歷時安全刪除)
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
if ("B".equals(item)) {
iterator.remove(); // 安全刪除當前元素
}
}
優(yōu)點:唯一能在遍歷時安全刪除元素的方式
缺點:代碼稍多
4.ListIterator(雙向遍歷,可以修改)
ListIterator<String> listIterator = list.listIterator();
while (listIterator.hasNext()) {
String item = listIterator.next();
if ("B".equals(item)) {
listIterator.set("B+"); // 修改當前元素
}
}
// 還可以倒著遍歷
while (listIterator.hasPrevious()) {
System.out.println(listIterator.previous());
}
5.Java 8的forEach + Lambda(很流行)
// 方式1:Lambda表達式
list.forEach(item -> System.out.println(item));
// 方式2:方法引用
list.forEach(System.out::println);
// 帶索引的(Java 8沒有原生支持,但可以這樣)
IntStream.range(0, list.size())
.forEach(i -> System.out.println(i + ": " + list.get(i)));Set遍歷
Set沒索引,所以只能用這幾種:
Set<String> set = new HashSet<>(Arrays.asList("A", "B", "C"));
// 1. 增強for循環(huán)
for (String item : set) {
System.out.println(item);
}
// 2. 迭代器
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
// 3. Java 8 forEach
set.forEach(item -> System.out.println(item));Map遍歷(重點!)
1.遍歷EntrySet(最推薦、最高效)
Map<String, Integer> map = new HashMap<>();
map.put("A", 1);
map.put("B", 2);
for (Map.Entry<String, Integer> entry : map.entrySet()) {
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key + "=" + value);
}為什么最推薦?:一次遍歷同時拿到key和value,不用再通過key去查value(map.get(key) 還有哈希計算的開銷)
2.遍歷KeySet(不推薦在遍歷中取值)
for (String key : map.keySet()) {
Integer value = map.get(key); // 這里又做了一次哈希查找
System.out.println(key + "=" + value);
}
缺點:多了一次 map.get(key) 的哈希查找,效率低
3.遍歷Values(只關心值時用)
for (Integer value : map.values()) {
System.out.println(value);
}
4.迭代器方式
Iterator<Map.Entry<String, Integer>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Integer> entry = iterator.next();
// 可以在遍歷時刪除
if ("A".equals(entry.getKey())) {
iterator.remove();
}
}
5.Java 8的forEach(最簡潔)
// Lambda表達式
map.forEach((key, value) -> System.out.println(key + "=" + value));
// 或者用entrySet的stream
map.entrySet().stream()
.filter(entry -> entry.getValue() > 1)
.forEach(entry -> System.out.println(entry.getKey()));遍歷時的注意事項
1.不要在foreach循環(huán)里直接增刪元素
// ? 錯誤!會拋 ConcurrentModificationException
for (String item : list) {
if ("B".equals(item)) {
list.remove(item); // 直接調(diào)用list的remove
}
}
// ? 正確!用迭代器的remove
Iterator<String> it = list.iterator();
while (it.hasNext()) {
if ("B".equals(it.next())) {
it.remove(); // 用迭代器自己的remove方法
}
}2.Java 8的removeIf(刪除元素新姿勢)
// 刪除所有值為"B"的元素 list.removeIf(item -> "B".equals(item)); // Map刪除滿足條件的entry map.entrySet().removeIf(entry -> entry.getValue() > 10);
3.并行遍歷(大數(shù)據(jù)量時考慮)
// 使用parallelStream(注意線程安全)
list.parallelStream().forEach(item -> {
// 這里可以并行處理
});
// 或者用ConcurrentHashMap的forEach(線程安全)
ConcurrentHashMap<String, Integer> concurrentMap = new ConcurrentHashMap<>();
concurrentMap.forEach(1, (key, value) -> System.out.println(key));實際工作怎么選?
日常開發(fā):
- 單純遍歷List/Set → 增強for循環(huán)(最簡潔)
- 遍歷Map → entrySet + 增強for 或 map.forEach()
- 需要在遍歷時刪除 → 迭代器 或 removeIf()
- Java 8+環(huán)境 → 多用 forEach + Lambda(代碼簡潔)
性能考慮:
- 大數(shù)據(jù)量List →
ArrayList用普通for最快,LinkedList用迭代器 - Map遍歷 → 一定用entrySet,別用keySet+get
記憶口訣:
- List遍歷:普通for要索引,增強for最方便,要刪就用迭代器
- Map遍歷:entrySet是王道,keySet效率低,Java8 forEach潮
這樣清楚了嗎?實際寫代碼時多試試,自然就熟練了!
到此這篇關于Java存儲數(shù)據(jù):數(shù)組與集合的文章就介紹到這了,更多相關java存儲數(shù)據(jù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringBoot整合RabbitMQ實現(xiàn)通配符模式
本文主要介紹了SpringBoot整合RabbitMQ實現(xiàn)通配符模式,包括依賴添加、配置、隊列與交換機聲明及綁定,生產(chǎn)者發(fā)送消息,兩個消費者分別接收并處理,驗證消息正確分發(fā)至不同隊列,感興趣的可以了解一下2025-06-06
springboot logback調(diào)整mybatis日志級別無效的解決
這篇文章主要介紹了springboot logback調(diào)整mybatis日志級別無效的解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-10-10
MyBatis解決Update動態(tài)SQL逗號的問題
這篇文章主要介紹了MyBatis解決Update動態(tài)SQL逗號的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01
解決springboot的aop切面不起作用問題(失效的排查)
這篇文章主要介紹了解決springboot的aop切面不起作用問題(失效的排查),具有很好的參考價值,希望對大家有所幫助。 一起跟隨小編過來看看吧2020-04-04
Java使用Spire.Presentation for Java庫合并PowerPoint的技術教
在現(xiàn)代企業(yè)和個人開發(fā)中,文檔處理是不可或缺的一環(huán),尤其是在報告演示、內(nèi)容整合等場景下,PowerPoint 文件的自動化處理需求日益增長,本文將深入探討如何利用 Java 編程語言,結(jié)合強大的 Spire.Presentation for Java庫,實現(xiàn)PowerPoiont文件的合并2026-01-01

