1.集合的概念与框架:
集合(Collection)是一组对象的容器,用于存储、操作和管理多个元素。
集合里的数据,我们称之为元素(elements);集合只能用来存储引用类型的数据,不能存储八大基本数据类型的数据。
集合的框架体系图:
1.1 常见的集合接口有:
List
:元素有序、可重复。例如ArrayList
和LinkedList
。ArrayList
底层基于数组实现,查询速度快,但插入和删除元素效率相对较低。LinkedList
底层基于双向链表实现,插入和删除元素效率高,但查询速度相对较慢。
Set
:元素无序、不可重复。例如HashSet
和TreeSet
。HashSet
通过哈希表实现,元素的存储和查找效率较高。TreeSet
底层基于红黑树实现,元素会自动排序。
Queue
:队列,遵循先进先出(FIFO)原则。例如PriorityQueue
,它可以根据元素的优先级来排序。
1.2 集合的优点:
1.方便对多个对象进行统一的管理和操作,如添加、删除、遍历等。
2.可以根据不同的需求选择不同的实现类,以达到最佳的性能和功能。
例如,如果需要频繁地在末尾添加和删除元素,可以选择
LinkedList
;如果需要快速随机访问元素,ArrayList
可能更合适。
2.Collection接口
2.1 Collection 接口简介
Collection 接口是 List、Set 和 Queue 接口的父接口,下面是Collection接口的实现与应用。
//创建一个集合
Collection<String> c1 = new ArrayList<String>();
//1.添加元素
c1.add("A");
c1.add("B");
c1.add("C");
//2.Boolean isEmpty()集合是否为空
Boolean isEmpty = c1.isEmpty();
//3.int size()返回集合元素的个数
c1.size();
//4.String toString()打印集合元素
System.out.println(c1);
//5.addAll(Collection c)添加集合
Collection<String> c2 = new ArrayList<String>();
c1.addAll(c2);
//6.boolean contains(Object o);是否包含某元素
boolean contains = c1.contains("C");
//7.boolean containsAll(Collection c)
boolean containsAll = c1.containsAll(c2);
System.out.println(containsAll);//8.boolean remove(Object o)移除集合里的一个元素
c1.remove("A");
//9.boolean removeAll(Collection<?> c)
//新建一个集合c4,添加元素"B","C"。测试c1移除c4.
Collection<String>c4 =new ArrayList<String>();
c4.add("");
c4.add("c");
c1.retainAll(c4);
System.out.println(c1);
//10.void clear(): 清空c1
c1.clear();
System.out.println(c1);
2.2 集合的迭代
迭代器Iterator,是一个接口, Collection集合中有一个方法 iterator() 可以获取这个接口的实现类 对象。在这个迭代器中,维护了一个引用,指向集合中的某一个元素。默认指向一个集合前不存在的元 素,可以认为是下标为-1的元素。
迭代器的工作原理:循环调用 next() 方法进行向后的元素指向,并返回新的指向的元素。同时,在向 后进行遍历的过程中,使用 hasNext() 判断是否还有下一个元素可以迭代。
Collection<Integer> c1 = new ArrayList();
c1.add(1);
c1.add(2);
c1.add(3);
c1.add(4);
c1.add(5);
//使用增强for循环
for (Integer i : c1) {
System.out.print(i+" ");
}
System.out.println();
//使用迭代器iterator进行遍历
Iterator<Integer> it = c1.iterator();
while (it.hasNext()) {
System.out.print(it.next()+" ");
}
}
3. List子接口
3.1 List子接口的简介:
-
List 是一个有序、且可重复的集合,集合中的每个元素都有其对应的顺序索引,从0开始。
-
List 允许使用重复元素,可以通过索引来访问指定位置的集合元素。
-
List 默认按元素的添加顺序设置元素的索引。
-
List 集合里添加了一些根据索引来操作集合元素的方法。
3.2 ArrayList和LinkedList
这两个类都是List接口的实现类(子类)。两者在实现上的底层原理对比
-
ArrayList是实现了基于动态数组的数据结构,对象存储在连续的位置上
-
LinkedList基于双链表的数据结构,链表中的每个节点都包含了前一个和后一个元素的引用。
-
对于随机访问get和set,ArrayList绝对优于LinkedList,因为LinkedList要移动指针。
-
对于插入和删除操作add和remove,LinkedList比较占优势,因为ArrayList要移动数据
3.3ArrayList和LinkedList常用的方法
创建ArrayList和LinkedList集合:
//创建一个ArrayList集合对象
List<String> list1 = new ArrayList<>();
//创建一个LinkedList集合对象
List<String> list2=new LinkedList<>();
元素的应用方法:
添加元素:list1.add("A");
获取元素:list1.get(int index);
查找元素:list.indexof("A");
移除元素:list1.remove(int index);
修改元素:list1.set(2,"A");
4.Queue子接口
双端队列Queue也是Collection的一个子接口,它也是常用的数据结构,可以将队列看成特殊的线性表,队列限制对线性表的访问方式:只能从一端添加(offer)元素,从另一端取出(poll)元素。
队列遵循先进先出(FIFO first Input First Output)
创建Queue集合:
Queue<String> queue = new LinkedList<>();
5.Set子接口
5.1 Set子接口的简介:
-
Set集合中的元素是无序的(取出的顺序与存入的顺序无关)
-
Set集合中的元素不能重复
5.2 HashSet,LinkedHashSet和TreeSet的用法
HashSet 是 Set 接口的典型实现,大多数时候使用 Set 集合时都使用这个实现类。HashSet 具有以下特点:(1) 不能保证元素的排列顺序(2) HashSet 不是线程安全的(3) 集合元素可以是 null。
LinkedHashSet 是 HashSet 的子类,不允许集合元素重复。
TreeSet 是 SortedSet 接口的实现类, TreeSet集合是用来对元素进行排序的,同样他也可以保证元素的唯一。TreeSet 可以确保集合元素处于排序状态。
5.3 数据存储结构和元素顺序
例如:如果先后添加元素 1、2、3 ,再次遍历集合时,可能的顺序是 3、1、2 。
HashSet
:基于哈希表实现,不保证元素的存储顺序。元素的存储顺序取决于其哈希值,这意味着在遍历集合时,元素的出现顺序是不可预测的。例如:先添加 5 ,再添加 10 ,遍历集合时,顺序就是 5 、10 。
LinkedHashSet
:继承自HashSet
,同时维护了一个双向链表来记录元素的插入顺序。因此,在遍历集合时,元素的顺序与插入顺序一致。例如:如果存储整数,那么遍历顺序就是升序,如 1 、2 、3 。
TreeSet
:基于红黑树实现,元素会按照自然顺序(如果元素实现了Comparable
接口)或者指定的比较器顺序进行排序。
6.集合的排序
6.1 Collections工具类排序
排序操作
reverse(List):反转 List 中元素的顺序
shuffle(List):对 List 集合元素进行随机排序
sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换
查找、替换
Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素
Object min(Collection)
Object min(Collection,Comparator)
int frequency(Collection,Object):返回指定集合中指定元素的出现次数
boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值
6.2 Comparator比较器排序
TreeSet比较器案例:
public class CustomComparatorExample { public static void main(String[] args) { Comparator<String> length = new Comparator<String>() { @Override public int compare(String s1, String s2) { return s2.length() - s1.length(); } }; TreeSet<String> treeSet = new TreeSet<>(length); treeSet.add("apple"); treeSet.add("banana"); treeSet.add("cherry"); treeSet.add("date"); // 使用普通 for 循环打印 for (int i = 0; i < treeSet.size(); i++) { System.out.println(treeSet.toArray()[i]); } } }
7.Map双列集合的接口
7.1Map接口的特点
1.Map接口,是集合框架中的另外一个父接口
2.Map存储的数据的特点:一对一的关系映射,称之为Key-Value-Pair
3.Map接口最常用的两个子类,是HashMap和TreeMap。
HashMap:底层使用了Hash表和红黑树的数据结构。
TreeMap:底层使用了二叉树。
4.Map的key不能重复,但是可以为null。value可以重复。
5.Map的Key可理解为是value索引,总能通过一个key找到一个具体的value。
6.Map里的元素也是无序的(存储顺序和存入顺序无关)。
7.2Map接口的应用
添加元素:V.put(K key,V value)
根据键删除元素:V.put(K key)
清除元素:void clear()
集合的长度:int size
7.3HashMap
HashMap
是 Java 中的一种常用集合类,用于存储键值对(Key,Value)的数据结构。
主要特点:
-
基于哈希表实现,允许存储
null
键和null
值。 -
不保证元素的顺序,即元素的存储和遍历顺序是不可预测的。
-
查找、插入和删除操作的平均时间复杂度为 O(1) ,在理想情况下性能较好。
存储学生的姓名和年龄:
public class HashMapExample {
public static void main(String[] args) {
HashMap<String, Integer> studentAges = new HashMap<>();
studentAges.put("Alice", 20);
studentAges.put("Bob", 22);
studentAges.put("Charlie", 19);int ageOfAlice = studentAges.get("Alice");
System.out.println("Alice 的年龄是:" + ageOfAlice);
}
}
存储商品的价格:
public class ProductPriceExample {
public static void main(String[] args) {
HashMap<String, Double> productPrices = new HashMap<>();
productPrices.put("iPhone", 8000.0);
productPrices.put("MacBook", 12000.0);
productPrices.put("iPad", 4000.0);double priceOfiPhone = productPrices.get("iPhone");
System.out.println("iPhone 的价格是:" + priceOfiPhone);
}
}
7.4TreeMap
TreeMap
是 Java 中的一种有序的键值对数据结构,它基于红黑树实现。
主要特点:
-
键必须实现
Comparable
接口或者在创建TreeMap
时提供一个自定义的比较器,以确定键的顺序。 -
元素按照键的自然顺序或者指定的比较器顺序进行排序。
按照学生姓名排序存储学生成绩:
public class TreeMapExample1 { public static void main(String[] args) { TreeMap<String, Student> studentScores = new TreeMap<>(); studentScores.put("Alice", new Student("Alice", 85)); studentScores.put("Bob", new Student("Bob", 90)); studentScores.put("Charlie", new Student("Charlie", 78)); //遍历 int size = studentScores.size(); for (int i = 0; i < size; i++) { Student student = (Student) studentScores.values().toArray()[i]; System.out.println(student); } } }
按照商品价格升序存储商品信息:
public class TreeMapExample2 { public static void main(String[] args) { Comparator<Product> priceComparator = new Comparator<Product>() { @Override public int compare(Product p1, Product p2) { return Double.compare(p1.getPrice(), p2.getPrice()); } }; TreeMap<Product, String> productDetails = new TreeMap<>(priceComparator); productDetails.put(new Product("iPhone", 8000.0), "苹果手机"); productDetails.put(new Product("MacBook", 12000.0), "苹果笔记本"); productDetails.put(new Product("iPad", 4000.0), "苹果平板"); // 遍历 int size = productDetails.size(); for (int i = 0; i < size; i++) { Product product = (Product) productDetails.keySet().toArray()[i]; System.out.println(product + " - " + productDetails.get(product)); } } }