Java存儲數(shù)據(jù)之?dāng)?shù)組與集合的詳細(xì)操作
Java存儲數(shù)據(jù):數(shù)組與集合
一、數(shù)組(Array)
1. 邏輯特征
- 固定大小:創(chuàng)建時(shí)指定長度,不能動(dòng)態(tài)改變
- 類型統(tǒng)一:所有元素必須是相同數(shù)據(jù)類型
- 內(nèi)存連續(xù):元素在內(nèi)存中連續(xù)存儲
- 效率高:通過索引直接訪問,時(shí)間復(fù)雜度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. 增強(qiáng)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ù)組大小固定,無法動(dòng)態(tài)擴(kuò)展 int[] arr = new int[3]; // arr[3] = 4; // ArrayIndexOutOfBoundsException // 問題2: 只能存儲同一類型數(shù)據(jù) // arr[0] = "hello"; // 編譯錯(cuò)誤 // 問題3: 缺少高級操作方法 // 沒有內(nèi)置的add(), remove(), contains()等方法
二、為什么需要集合(Collection)
1. 數(shù)組的不足
- 大小固定:不能動(dòng)態(tài)增長或收縮
- 功能有限:缺少增刪改查的高級方法
- 類型限制:只能存儲相同類型
- 代碼繁瑣:需要手動(dòng)處理很多邏輯
2. 集合的優(yōu)勢
- 動(dòng)態(tài)擴(kuò)容:自動(dòng)調(diào)整大小
- 功能豐富:提供各種操作方法
- 類型靈活:通過泛型支持類型安全
- 算法支持:內(nèi)置排序、查找等算法
三、集合知識體系
Java集合框架 (Java Collections Framework)
│
├── Collection接口 (單列集合)
│ ├── List接口 (有序、可重復(fù))
│ │ ├── ArrayList: 數(shù)組實(shí)現(xiàn),查詢快,增刪慢
│ │ ├── LinkedList: 鏈表實(shí)現(xiàn),增刪快,查詢慢
│ │ └── Vector: 線程安全的ArrayList(已過時(shí))
│ │
│ ├── Set接口 (無序、不可重復(fù))
│ │ ├── HashSet: 哈希表實(shí)現(xiàn)
│ │ ├── LinkedHashSet: 有序的HashSet
│ │ └── TreeSet: 紅黑樹實(shí)現(xiàn),可排序
│ │
│ └── Queue接口 (隊(duì)列)
│ ├── LinkedList: 也實(shí)現(xiàn)了Queue
│ ├── PriorityQueue: 優(yōu)先級隊(duì)列
│ └── ArrayDeque: 雙端隊(duì)列
│
└── Map接口 (雙列集合,鍵值對)
├── HashMap: 最常用的Map
├── LinkedHashMap: 有序的HashMap
├── TreeMap: 可排序的Map
└── Hashtable: 線程安全的Map(已過時(shí))四、主要集合類示例
1. ArrayList(最常用)
// 創(chuàng)建ArrayList
List<String> list = new ArrayList<>();
// 添加元素(自動(dòng)擴(kuò)容)
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); // 尾部添加 // 作為隊(duì)列使用 linkedList.offer(30); // 入隊(duì) int head = linkedList.poll(); // 出隊(duì) // 作為棧使用 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"); // 重復(fù),不會添加
// 遍歷(無序)
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ù)組 | 集合 |
|---|---|---|
| 大小 | 固定,聲明時(shí)確定 | 動(dòng)態(tài),可自動(dòng)擴(kuò)容 |
| 類型 | 必須統(tǒng)一 | 通過泛型支持多種類型 |
| 性能 | 訪問快(O(1)) | 實(shí)現(xiàn)不同,性能各異 |
| 功能 | 基本操作 | 豐富的高級操作 |
| 存儲 | 基本類型和對象 | 只能存儲對象 |
| 線程安全 | 不安全 | 大部分不安全 |
六、最佳實(shí)踐建議
- 優(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語言的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu),簡單高效但功能有限
- 集合是對數(shù)組的封裝和擴(kuò)展,提供了更強(qiáng)大、更靈活的數(shù)據(jù)管理能力
- 現(xiàn)代Java開發(fā)中,集合是首選,數(shù)組主要用于:
- 性能敏感的場景
- 處理基本數(shù)據(jù)類型
- 與遺留代碼或API交互
- 理解不同集合的特性,根據(jù)需求選擇最合適的工具
實(shí)際開發(fā)中,ArrayList和HashMap是最常用的集合類,掌握了它們就解決了80%的數(shù)據(jù)存儲問題。
好的,專門說說遍歷集合!這是天天要用的操作,分幾種情況給你講清楚。
List遍歷(最常用)
1.普通for循環(huán)(有索引時(shí)用)
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)點(diǎn):能拿到索引,方便操作
缺點(diǎn):只有 ArrayList 這種基于數(shù)組的用著快,LinkedList 用這個(gè)就慢(因?yàn)橐粋€(gè)個(gè)數(shù)過去)
2.增強(qiáng)for循環(huán)(最常用、最簡潔)
for (String item : list) {
System.out.println(item);
}
優(yōu)點(diǎn):寫法簡單,可讀性好
缺點(diǎn):遍歷時(shí)不能修改集合(刪除、新增會拋異常)
3.迭代器Iterator(可以在遍歷時(shí)安全刪除)
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
if ("B".equals(item)) {
iterator.remove(); // 安全刪除當(dāng)前元素
}
}
優(yōu)點(diǎn):唯一能在遍歷時(shí)安全刪除元素的方式
缺點(diǎn):代碼稍多
4.ListIterator(雙向遍歷,可以修改)
ListIterator<String> listIterator = list.listIterator();
while (listIterator.hasNext()) {
String item = listIterator.next();
if ("B".equals(item)) {
listIterator.set("B+"); // 修改當(dāng)前元素
}
}
// 還可以倒著遍歷
while (listIterator.hasPrevious()) {
System.out.println(listIterator.previous());
}
5.Java 8的forEach + Lambda(很流行)
// 方式1:Lambda表達(dá)式
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. 增強(qiáng)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遍歷(重點(diǎn)?。?/h3>
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);
}為什么最推薦?:一次遍歷同時(shí)拿到key和value,不用再通過key去查value(map.get(key) 還有哈希計(jì)算的開銷)
2.遍歷KeySet(不推薦在遍歷中取值)
for (String key : map.keySet()) {
Integer value = map.get(key); // 這里又做了一次哈希查找
System.out.println(key + "=" + value);
}
缺點(diǎn):多了一次 map.get(key) 的哈希查找,效率低
3.遍歷Values(只關(guān)心值時(shí)用)
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();
// 可以在遍歷時(shí)刪除
if ("A".equals(entry.getKey())) {
iterator.remove();
}
}
5.Java 8的forEach(最簡潔)
// Lambda表達(dá)式
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()));遍歷時(shí)的注意事項(xiàng)
1.不要在foreach循環(huán)里直接增刪元素
// ? 錯(cuò)誤!會拋 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ù)量時(shí)考慮)
// 使用parallelStream(注意線程安全)
list.parallelStream().forEach(item -> {
// 這里可以并行處理
});
// 或者用ConcurrentHashMap的forEach(線程安全)
ConcurrentHashMap<String, Integer> concurrentMap = new ConcurrentHashMap<>();
concurrentMap.forEach(1, (key, value) -> System.out.println(key));實(shí)際工作怎么選?
日常開發(fā):
- 單純遍歷List/Set → 增強(qiáng)for循環(huán)(最簡潔)
- 遍歷Map → entrySet + 增強(qiáng)for 或 map.forEach()
- 需要在遍歷時(shí)刪除 → 迭代器 或 removeIf()
- Java 8+環(huán)境 → 多用 forEach + Lambda(代碼簡潔)
性能考慮:
- 大數(shù)據(jù)量List →
ArrayList用普通for最快,LinkedList用迭代器 - Map遍歷 → 一定用entrySet,別用keySet+get
記憶口訣:
- List遍歷:普通for要索引,增強(qiáng)for最方便,要?jiǎng)h就用迭代器
- Map遍歷:entrySet是王道,keySet效率低,Java8 forEach潮
這樣清楚了嗎?實(shí)際寫代碼時(shí)多試試,自然就熟練了!
到此這篇關(guān)于Java存儲數(shù)據(jù):數(shù)組與集合的文章就介紹到這了,更多相關(guān)java存儲數(shù)據(jù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java存儲數(shù)據(jù)至Rredis之@RedisHash實(shí)現(xiàn)過程
- Java 數(shù)組(Array)存儲數(shù)據(jù)的“排排坐”(最新推薦)
- java靈活使用mysql中json類型字段存儲數(shù)據(jù)詳解
- Java中的HashSet集合存儲數(shù)據(jù)的結(jié)構(gòu)詳解
- 淺談Java中的集合存儲數(shù)據(jù)后,輸出數(shù)據(jù)的有序和無序問題
- JAVA基礎(chǔ)之?dāng)?shù)組和集合區(qū)別對比分析
- Java中的數(shù)組與集合基本用法詳解
- java集合與數(shù)組的相同點(diǎn)和不同點(diǎn)
相關(guān)文章
深入探究SpringBoot攔截器的自定義設(shè)計(jì)與實(shí)現(xiàn)全攻略
攔截器是Spring框架提供的核心功能之?,主要用來攔截用戶的請求,在指定方法前后,根據(jù)業(yè)務(wù)需要執(zhí)行預(yù)先設(shè)定的代碼,本文將給大家和大家一起深入探究SpringBoot攔截器的自定義設(shè)計(jì)與實(shí)現(xiàn),需要的朋友可以參考下2024-05-05
探索Java中的equals()和hashCode()方法_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了探索Java中的equals()和hashCode()方法的相關(guān)資料,需要的朋友可以參考下2017-05-05
基于SpringBoot實(shí)現(xiàn)輕量級的動(dòng)態(tài)定時(shí)任務(wù)調(diào)度的方法
本文介紹了如何在SpringBoot框架中實(shí)現(xiàn)輕量級的動(dòng)態(tài)定時(shí)任務(wù)調(diào)度,通過將任務(wù)以類為基礎(chǔ)單位,并通過配置數(shù)據(jù)進(jìn)行任務(wù)讀取和反射生成任務(wù)對象,感興趣的朋友跟隨小編一起看看吧2024-11-11
mybatis自動(dòng)生成時(shí)如何設(shè)置不生成Example類詳解
這篇文章主要給大家介紹了關(guān)于mybatis自動(dòng)生成時(shí)如何設(shè)置不生成Example類的相關(guān)資料,文中介紹的非常詳細(xì),對大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧。2017-05-05
Springmvc項(xiàng)目web.xml中servlet-mapping路徑映射配置注意說明
這篇文章主要介紹了Springmvc項(xiàng)目web.xml中servlet-mapping路徑映射配置注意說明,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12

