我将从Java集合框架的基础概念、常见接口与类的特点及区别、底层数据结构、线程安全等方面入手,结合应用实例,为你提供一篇全面的Java集合容器学习文章。
Java集合框架是Java提供的一组接口和类,用于表示和处理一组对象。它就像是一个强大的工具箱,包含多种数据结构,如列表、集合、队列和映射,以及相关的算法,极大地方便了开发者对数据的存储、检索、操作和管理。通过使用集合框架,我们可以将数据对象集中管理,避免了手动管理数据带来的复杂性和潜在错误。
数组和集合都用于存储数据,但它们有明显的区别:
int
、double
等),也可以存储引用数据类型。然而,集合只能存储引用数据类型,若要存储基本数据类型,需要使用对应的包装类(如Integer
、Double
等)。Collection接口是Java集合框架中最基本的接口,它定义了集合操作的通用方法,如添加元素、删除元素、判断集合是否为空、获取集合大小等。所有其他的集合接口(如List、Set、Queue)都继承自Collection接口。
List接口是Collection接口的子接口,它代表一个有序的集合,允许元素重复。在List中,元素按照插入的顺序存储,并且每个元素都有对应的索引,可以通过索引快速访问元素。常见的List实现类有ArrayList、LinkedList和Vector。
List<Student> studentList = new ArrayList<>();
studentList.add(new Student("Alice", 20));
studentList.add(new Student("Bob", 22));
Student student = studentList.get(0); // 通过索引快速获取学生对象
Queue<Task> taskQueue = new LinkedList<>();
taskQueue.add(new Task("Task1"));
taskQueue.add(new Task("Task2"));
Task task = taskQueue.poll(); // 从队列头部取出任务
synchronized
关键字进行同步,因此它是线程安全的。然而,由于同步操作会带来性能开销,所以在单线程环境下,其性能比ArrayList低。Set接口也是Collection接口的子接口,它代表一个无序的集合,不允许元素重复,即集合中每个元素都是唯一的。常见的Set实现类有HashSet、LinkedHashSet和TreeSet。
equals
方法判断),则添加操作会失败,集合中不会出现重复的元素。null
元素,但由于其无序性,null
元素的位置是不确定的。Set<String> wordSet = new HashSet<>();
String[] words = "this is a sample text this text is for testing".split(" ");
for (String word : words) {
wordSet.add(word);
}
System.out.println(wordSet); // 输出不重复的单词集合
LinkedHashSet<String> pageSet = new LinkedHashSet<>();
pageSet.add("HomePage");
pageSet.add("ProductPage");
pageSet.add("CartPage");
for (String page : pageSet) {
System.out.println(page); // 按照插入顺序输出页面
}
Comparable
接口的类)或者自定义的比较器(通过Comparator
接口)进行排序。在插入元素时,会根据排序规则将元素插入到合适的位置,以保证集合的有序性。null
元素,因为在排序过程中null
无法参与比较。Comparable
接口,按照成绩从高到低进行排序。例如:class Student implements Comparable<Student> {
private String name;
private int score;
public Student(String name, int score) {
this.name = name;
this.score = score;
}
@Override
public int compareTo(Student other) {
return Integer.compare(other.score, this.score); // 按成绩从高到低排序
}
@Override
public String toString() {
return name + ": " + score;
}
}
TreeSet<Student> studentTreeSet = new TreeSet<>();
studentTreeSet.add(new Student("Alice", 90));
studentTreeSet.add(new Student("Bob", 85));
studentTreeSet.add(new Student("Charlie", 95));
for (Student student : studentTreeSet) {
System.out.println(student); // 输出按成绩排序的学生列表
}
Map接口不是Collection接口的子接口,它代表一个键值对(key - value)的映射集合。在Map中,每个键最多映射到一个值(但一个值可以被多个键映射)。常见的Map实现类有HashMap、LinkedHashMap、TreeMap、Hashtable和ConcurrentHashMap。
null
作为键和值,但需要注意的是,由于null
键的哈希值为0,所以在哈希表中只能有一个null
键。Map<Integer, User> userMap = new HashMap<>();
userMap.put(1, new User("Alice", 25));
userMap.put(2, new User("Bob", 30));
User user = userMap.get(1); // 根据用户ID获取用户对象
class LRUCache extends LinkedHashMap<Integer, Integer> {
private int capacity;
public LRUCache(int capacity) {
super(capacity, 0.75f, true);
this.capacity = capacity;
}
@Override
protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
return size() > capacity;
}
}
LRUCache cache = new LRUCache(3);
cache.put(1, 100);
cache.put(2, 200);
cache.put(3, 300);
cache.get(2); // 访问键2,将其移动到链表尾部
cache.put(4, 400); // 缓存满,移除最近最少使用的键1
Comparable
接口的类)或者自定义的比较器(通过Comparator
接口)进行排序。在插入键值对时,会根据键的排序规则将其插入到合适的位置,以保证集合的有序性。null
作为键,因为在排序过程中null
无法参与比较,但允许使用null
作为值。Comparable
接口,按照学号从小到大排序。例如:class StudentGrade {
private int studentId;
private int grade;
public StudentGrade(int studentId, int grade) {
this.studentId = studentId;
this.grade = grade;
}
@Override
public String toString() {
return "StudentId: " + studentId + ", Grade: " + grade;
}
}
TreeMap<Integer, StudentGrade> gradeMap = new TreeMap<>();
gradeMap.put(101, new StudentGrade(101, 90));
gradeMap.put(103, new StudentGrade(103, 85));
gradeMap.put(102, new StudentGrade(102, 95));
for (Map.Entry<Integer, StudentGrade> entry : gradeMap.entrySet()) {
System.out.println(entry.getValue()); // 按学号顺序输出学生成绩信息
}
synchronized
关键字进行同步,因此它是线程安全的。然而,由于同步操作会带来性能开销,所以在单线程环境下,其性能比HashMap低。import java.util.Hashtable;
public class WordCount {
public static void main(String[] args) {
String text = "hello world hello java";
String[] words = text.split(" ");
Hashtable<String, Integer> wordCount = new Hashtable<>();
for (String word : words) {
// 若单词已存在,增加计数;否则初始化为 1
wordCount.put(word, wordCount.getOrDefault(word, 0) + 1);
}
System.out.println("单词统计结果:");
for (String key : wordCount.keySet()) {
System.out.println(key + ": " + wordCount.get(key));
}
}
}
输出结果:
plaintext
单词统计结果:
java: 1
world: 1
hello: 2
import java.util.Hashtable;
public class CacheExample {
private static Hashtable<Integer, Integer> cache = new Hashtable<>();
public static int fibonacci(int n) {
if (n <= 1) return n;
// 检查缓存中是否已有结果
if (cache.containsKey(n)) {
return cache.get(n);
}
// 计算并缓存结果
int result = fibonacci(n-1) + fibonacci(n-2);
cache.put(n, result);
return result;
}
public static void main(String[] args) {
System.out.println("斐波那契数列第10项:" + fibonacci(10));
System.out.println("缓存内容:" + cache);
}
}
输出结果:
plaintext
斐波那契数列第10项:55
缓存内容:{2=1, 3=2, 4=3, 5=5, 6=8, 7=13, 8=21, 9=34, 10=55}
import java.util.Hashtable;
public class MultiThreadExample {
private static Hashtable<String, Integer> scores = new Hashtable<>();
public static void main(String[] args) throws InterruptedException {
// 初始化分数
scores.put("Alice", 0);
scores.put("Bob", 0);
// 创建两个线程同时更新分数
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
scores.put("Alice", scores.get("Alice") + 1);
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
scores.put("Bob", scores.get("Bob") + 1);
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("最终分数:");
System.out.println("Alice: " + scores.get("Alice")); // 输出 1000
System.out.println("Bob: " + scores.get("Bob")); // 输出 1000
}
}
Java 集合,集合容器,面试题,ArrayList,HashMap,LinkedList,HashSet,ConcurrentHashMap, 集合框架,Collection 接口,List 接口,Set 接口,Map 接口,集合遍历,集合性能
`
代码获取方式
https://pan.quark.cn/s/14fcf913bae6
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。