一篇文章来你学完Java中的集合(超详细)

目录

一:集合的体系

Collection接口体系 

Map接口体系

二:Collection集合

Collection的常见方法

迭代器

迭代器的基本方法

代码解释

增强for循环

语法

注意事项

使用 Consumer 和 Lambda 表达式遍历集合

案例演示

集合中存储元素本质

对象和引用

集合存储引用

示例:添加对象到ArrayList

总结

List 集合

List 集合中的特有方法

ArrayList集合 

LinkedList集合

LinkedList集合的底层原理

LinkedList的底层实现:

双向链表的特点

LinkedList的特有方法

 LinkedList 集合业务场景 

Set集合

前言

HashSet

LinkedHashSet

TreeSet

HashSet集合详解

HashSet集合的底层原理

一、哈希值概述

二、对象哈希值的特点

HashSet集合的底层实现 

TreeSet集合详解

TreeSet自定义排序规则

集合的并发修改异常

并发修改异常示例

如何避免并发修改异常

Collections

三:Map集合


一:集合的体系

Java中的集合体系结构是一个为表示和操作集合而设计的统一标准的体系结构,它主要由两大接口体系构成:Collection接口体系和Map接口体系。

Collection接口体系 

Collection接口是集合框架的根接口,用于表示一组元素的集合。它定义了集合的基本操作,如添加、删除、遍历等。Collection接口体系主要包括以下几个子接口:

  1. List
    • 特性:有序的集合,允许元素重复,有索引。
    • 常用实现类
      • ArrayList:基于动态数组实现,适合随机访问。
      • LinkedList:基于链表实现,适合频繁的插入和删除操作。
  2. Set
    • 特性:无序的集合,不允许元素重复,无索引。
    • 常用实现类
      • HashSet:基于哈希表实现,不保证元素的顺序,效率较高。
      • LinkedHashSet:继承自HashSet,通过链表维护元素的插入顺序。
      • TreeSet:基于红黑树实现,可以对元素进行排序。

Map接口体系

Map接口用于存储键值对(key-value pairs),一个键可以映射到最多一个值。Map接口体系主要包括以下几个实现类:

  1. HashMap
    • 特性:基于哈希表的实现,提供快速的键查找能力。
    • 注意:不保证映射的顺序,且允许一个键为null和多个值为null
  2. LinkedHashMap
    • 特性:继承自HashMap,同时维护了一个双向链表来记录插入顺序或访问顺序。
    • 注意:根据创建时指定的参数,可以维护插入顺序或访问顺序。
  3. TreeMap
    • 特性:基于红黑树实现,可以对键进行排序。
    • 注意:自然排序或根据创建时提供的Comparator进行排序。

二:Collection集合

Collection的常见方法

Collection是单列集合的祖宗,它规定的方法是全部单列集合都会继承的。所以我们优先学习Collection的常见方法。

下面我将详细讲解Java中Collection接口的一些常见方法,并通过代码示例来说明它们的使用。

                  方法名                           说明
 boolean add(E e) 把改定的对象添加到当前集合中
 boolean addAll(Collection<? extends E> c) 向集合中添加另一个集合的所有元素
 void clear() 移除集合中的所有元素
boolean contains(Object o) 检查集合是否包含指定的元素
boolean remove(Object o) 从集合中移除指定的元素
int size() 返回集合中的元素数量
 boolean isEmpty() 检查集合是否为空
Object[] toArray() 把集合中的元素存储到数组中

1. boolean add(E e)

向集合中添加一个元素。如果集合改变(即元素被添加),则返回true

import java.util.ArrayList;  
import java.util.Collection;  
  
public class CollectionExample {  
    public static void main(String[] args) {  
        Collection<String> collection = new ArrayList<>();  
        boolean result = collection.add("Hello");  
        System.out.println(result);

        collection.add("小白杨");
        System.out.println(collection);
        
        输出:
        true
        [Hello, 小白杨]
    }  
}

2. boolean addAll(Collection<? extends E> c)

向集合中添加另一个集合的所有元素。

import java.util.ArrayList;  
import java.util.Arrays;  
import java.util.Collection;  
  
public class CollectionExample {  
    public static void main(String[] args) {  
        Collection<String> collection1 = new ArrayList<>(Arrays.asList("Hello", "World"));  
        Collection<String> collection2 = new ArrayList<>(Arrays.asList("Java", "Programming"));  
  
        collection1.addAll(collection2);  
  
        System.out.println(collection1); 
        // 输出: [Hello, World, Java, Programming]  
    }  
}

3. void clear()

移除集合中的所有元素。

import java.util.ArrayList;  
import java.util.Collection;  
  
public class CollectionExample {  
    public static void main(String[] args) {  
        Collection<String> collection = new ArrayList<>(Arrays.asList("Hello", "World"));  
  
        collection.clear();  
  
        System.out.println(collection.isEmpty()); // 输出: true  
    }  
}

4. boolean contains(Object o)

检查集合是否包含指定的元素。

import java.util.ArrayList;  
import java.util.Collection;  
  
public class CollectionExample {  
    public static void main(String[] args) {  
        Collection<String> collection = new ArrayList<>(Arrays.asList("Hello", "World"));  
  
        boolean containsHello = collection.contains("Hello");  
        System.out.println("Contains 'Hello': " + containsHello); 
// 输出: Contains 'Hello': true  
  
        boolean containsJava = collection.contains("Java");  
        System.out.println("Contains 'Java': " + containsJava); 
// 输出: Contains 'Java': false  
    }  
}

5. boolean remove(Object o)

从集合中移除指定的元素(如果存在)。

import java.util.ArrayList;  
import java.util.Collection;  
  
public class CollectionExample {  
    public static void main(String[] args) {  
        Collection<String> collection = new ArrayList<>(Arrays.asList("Hello", "World"));  
  
        boolean removed = collection.remove("Hello");  
        System.out.println("Removed 'Hello': " + removed);
// 输出: Removed 'Hello': true  
  
        System.out.println(collection); 
// 输出: [World]  
    }  
}

6. int size()

返回集合中的元素数量。

import java.util.ArrayList;  
import java.util.Collection;  
  
public class CollectionExample {  
    public static void main(String[] args) {  
        Collection<String> collection = new ArrayList<>(Arrays.asList("Hello", "World", "Java"));  
  
        int size = collection.size();  
        System.out.println("Size of the collection: " + size); 
// 输出: Size of the collection: 3  
    }  
}

7. boolean isEmpty()

检查集合是否为空。

import java.util.ArrayList;  
import java.util.Collection;  
  
public class CollectionExample {  
    public static void main(String[] args) {  
        Collection<String> collection = new ArrayList<>();  
  
        boolean isEmpty = collection.isEmpty();  
        System.out.println("Is the collection empty? " + isEmpty); 
// 输出: Is the collection empty? true  
  
        collection.add("Hello");  
        isEmpty = collection.isEmpty();  
        System.out.println("Is the collection empty now? " + isEmpty); 
// 输出: Is the collection empty now? false  
    }  
}

8. Object[] toArray()

返回一个包含集合中所有元素的数组。返回的数组是对象类型,因此你可能需要类型转换来访问具体的元素。

import java.util.ArrayList;  
import java.util.Collection;  
  
public class CollectionExample {  
    public static void main(String[] args) {  
        Collection<String> collection = new ArrayList<>(Arrays.asList("Hello", "World", "Java"));  
  
        Object[] array = collection.toArray();  
        for (Object obj : array) {  
            System.out.println(obj); // 输出集合中的每个元素  
        }  
  
        // 如果你知道数组的类型,可以这样做:  
        String[] stringArray = collection.toArray(new String[0]);  
        for (String str : stringArray) {  
            System.out.println(str); // 同样输出集合中的每个元素,但避免了类型转换  
        }  
    }  
}

迭代器

由于Collection接口不直接支持通过索引访问元素(这是List接口的特性),因此它提供了一种名为迭代器(Iterator)的机制来遍历集合中的元素。

迭代器是一个对象,它提供了一种统一的方法来遍历集合中的元素,而无需了解集合的内部结构。迭代器允许在遍历集合时移除元素,但不允许直接添加元素(尽管某些集合,如List,提供了自己的方法来在迭代过程中添加元素,但这与迭代器本身无关)。

迭代器的基本方法
  • boolean hasNext():检查集合中是否还有元素未被遍历。
  • E next():返回集合中下一个元素,并将迭代器的游标向前移动一位。如果集合中没有更多元素,则抛出NoSuchElementException
  • void remove():从集合中移除通过next()方法返回的最后一个元素(迭代器必须先调用next()方法,才能调用remove()方法,否则会抛出IllegalStateException)。
代码解释

以下是一个使用迭代器遍历Collection中元素的示例代码:

import java.util.ArrayList;  
import java.util.Collection;  
import java.util.Iterator;  
  
public class IteratorExample {  
    public static void main(String[] args) {  
        // 创建一个Collection集合  
        Collection<String> collection = new ArrayList<>();  
        collection.add("Apple");  
        collection.add("Banana");  
        collection.add("Cherry");  
  
        // 获取迭代器  
        Iterator<String> iterator = collection.iterator();  
  
        // 使用迭代器遍历集合  
        while (iterator.hasNext()) {  
            // 迭代器移动到下一个元素,并返回当前(已移动前)的元素  
            String fruit = iterator.next();   
            System.out.println(fruit); // 打印当前元素  
输出:
Apple
Banana
Cherry
//当读取到最后一个数据,迭代器移到下一个位置,此时已经没有元素了。hasNext返回的就是false。
  

        }  
  
        // 注意:此时迭代器已经遍历完集合,再调用next()会抛出NoSuchElementException  
    }  
}

增强for循环

①增强for可以用来遍历集合或者数组。

②增长for遍历集合,本质就是迭代器遍历集合的简化写法。

语法

对于数组:

for(类型 变量名 : 数组名) {  
    // 循环体  
}

示例:

int[] numbers = {1, 2, 3, 4, 5};  
for(int number : numbers) {  
    System.out.println(number);  
}

对于集合(Collection及其子接口如ListSet等):

for(类型 变量名 : 集合名) {  
    // 循环体  
}

示例:

List<String> fruits = new ArrayList<>();  
fruits.add("Apple");  
fruits.add("Banana");  
fruits.add("Cherry");  
  
for(String fruit : fruits) {  
    System.out.println(fruit);  
}
输出:
Apple  
Banana  
Cherry
注意事项
  1. 修改集合:虽然增强型for循环简化了遍历集合的过程,但它不直接支持在遍历过程中修改集合(如添加或删除元素)。如果需要在遍历过程中修改集合,应该考虑使用传统的for循环或迭代器,并通过迭代器的remove()方法来安全地删除元素。

  2. 类型推断:在增强型for循环中,变量变量名的类型是由数组或集合中元素的类型自动推断的,这得益于Java的类型推断机制(也称为“目标类型推断”)。

  3. 只读访问:由于增强型for循环不提供直接访问元素索引的方式,因此它主要用于对集合进行只读遍历。如果需要基于索引的访问,则应考虑使用传统的for循环或其他方法。

  4. 适用范围:增强型for循环特别适用于遍历数组和实现了Iterable接口的集合(如ListSet等)。对于没有实现Iterable接口的集合(如Map),则不能直接使用增强型for循环进行遍历,但可以通过entrySet()keySet()values()方法将其转换为可迭代对象后再进行遍历。

使用 Consumer 和 Lambda 表达式遍历集合

由于Consumer<T>是一个函数式接口,接口不能创建对象。所以你可以直接去new一个匿名内部类的对象出来。

import java.util.Arrays;
import java.util.List;

public class LambdaExample {
    public static void main(String[] args) {
        List<String> fruits = Arrays.asList("Apple", "Banana", "Cherry");

        // 使用Lambda表达式遍历List
        fruits.forEach(fruit -> System.out.println(fruit));
    }
}

 在没有Lambda表达式和默认方法之前,你可能需要这样遍历集合:

for (String fruit : fruits) {  
    System.out.println(fruit);  
}

或者,使用迭代器:

Iterator<String> iterator = fruits.iterator();  
while (iterator.hasNext()) {  
    String fruit = iterator.next();  
    System.out.println(fruit);  
}

但是,从Java 8开始,你可以使用 forEach 方法和Lambda表达式来更简洁地实现相同的功能:

fruits.forEach(new Consumer<String>() {  
    @Override  
    public void accept(String fruit) {  
        System.out.println(fruit);  
    }  
});

然而,上面的写法仍然使用了匿名内部类。通过Lambda表达式,我们可

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值