集合
实际开发中,常涉及各种数据结构,如列表、栈、队列等。他们能存储大量对象,有不同的存储特色和操作模式。Java将支持数据结构的一组类、接口统称为集合框架 ,封装在java.util包中。
集合框架中的很多类功能是相似的,所以用接口来规范类。Collection和Map被视为Java集合框架里的两个根接口,代表两种不同特色数据集:集合和映射。集合直接存储对象,映射则是以键值对<key,value>方式存储对象。
Collection集合
Collection集合是用来存放对象的容器,相对于数组而言它更加灵活,方便。通常把集合理解为加强的数组结构,因为它可以完成数组的所有能完成的事,并且还提供了很多可以使用的方法。要想学习集合就必须了解集合的结构。
所有Collection的集合类都要继承Collection,它的两个直接子类,List和Set。这两个是接口不能直接创建对象,需要创建具体的子类对象。这两个子类的区别在于:
- List 的特点是有索引、存取有序、可重复。
- Set 的特点是无索引、存取无序(LinkedHashSet除外)、不可重复。
List有两个重要的子类,一个是ArrayList和LinkedList。其中ArrayList是类似数组的存储结构,它的特点就是查询效率很高,但是添加删除元素效率很低。因为如果要改动某个地方,那么那个位置后面的元素都需要移动,所以效率低下。但是LinkedList就不一样,它是链表结构,对于链表结构来讲由于没有下标,所以查找效率低下,但是更改元素效率却很高。详情情况可参考数据结构里链表的增删。
1 Collection接口中的常用方法
Collection集合常用方法如下:
- public boolean add(E e):把给定的对象添加到当前集合中 。
- boolean addAll(Collection<? extends E> c) 把集合C中的元素全部添加到集合中,若指定集合元素改变返回true
- public void clear():清空集合中所有的元素。
- public boolean remove(E e):把给定的对象在当前集合中删除。
- boolean removeAll(Collection<?> c) 删除指定集合包含集合c的元素
- public boolean contains(E e):判断当前集合中是否包含给定的对象。
- public boolean isEmpty():判断当前集合是否为空。
- public int size():返回集合中元素的个数。 public Object[] toArray():把集合中的元素,存储到数组中。
- T[] toArray(T[] a) 将集合转换为T类型的数组
1.1 Collection集合的遍历
迭代器遍历
Java迭代器(Iterator)是 Java 集合框架中的一种机制,是一种用于遍历集合(如列表、集合和映射等)的接口。它提供了一种统一的方式来访问集合中的元素,而不需要了解底层集合的具体实现细节。
迭代器接口定义了几个方法,最常用的是以下三个:
-
-
next() - 返回迭代器的下一个元素,并将迭代器的指针移到下一个位置。
-
hasNext() - 用于判断集合中是否还有下一个元素可以访问。
-
remove() - 从集合中删除迭代器最后访问的元素(可选操作)。
-
Iterator 类位于 java.util 包中,使用前需要引入它,语法格式如下:
import java.util.Iterator; // 引入 Iterator 类
通过使用迭代器,我们可以逐个访问集合中的元素,而不需要使用传统的 for 循环或索引。这种方式更加简洁和灵活,并且适用于各种类型的集合。
集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前。
举例:
1、获取一个迭代器
// 引入 ArrayList 和 Iterator 类 import java.util.ArrayList; import java.util.Iterator; public class RunoobTest { public static void main(String[] args) { // 创建集合 ArrayList<String> sites = new ArrayList<String>(); sites.add("好"); sites.add("好"); sites.add("学"); sites.add("习"); // 获取迭代器 Iterator<String> it = sites.iterator(); // 输出集合中的第一个元素 System.out.println(it.next()); } }
2、循环集合元素
// 引入 ArrayList 和 Iterator 类 import java.util.ArrayList; import java.util.Iterator; public class RunoobTest { public static void main(String[] args) { // 创建集合 ArrayList<String> sites = new ArrayList<String>(); sites.add("好"); sites.add("好"); sites.add("学"); sites.add("习"); // 获取迭代器 Iterator<String> it = sites.iterator(); // 输出集合中的所有元素 while(it.hasNext()) { System.out.println(it.next()); } } }
foreach遍历
foreach语句是java5的新特征之一,在遍历数组、集合方面,foreach为开发人员提供了极大的方便。foreach语句是for语句的特殊简化版本,但是foreach语句并不能完全取代for语句,然而,任何的foreach语句都可以改写为for语句版本。
public class Demo{ public void static void main(String[] args){ int[] arr = new int[]{1,3,6,2,9}; for(int e : arr){ System.out.print(e); } } }
任务需求
创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合。
1.2 List集合概念和特点
List集合概述
List集合是有序集合(也称为序列),用户可以精确控制列表中每个元素的插入位置。用户可以通过整数索引访问元素,并搜索列表中的元素。 List集合特点: 有索引 、可以存储重复元素 、元素存取有序.
List 接口实现的类有: ArrayList(实现动态数组),Vector(实现动态数组),LinkedList(实现链表),Stack(实现堆栈)。 ArrayList集合 :底层是数组结构实现,查询快、增删慢 LinkedList集合 :底层是链表结构实现,查询慢、增删快
List集合的常用方法
(1)ArrayList集合的特有方法
(2)LinkedList集合的特有方法
任务需求
实现医院病人排队叫号就诊程序,效果如下:
1.3 Set集合
注重独一无二的性质,该体系集合可以知道某物是否已近存在于集合中,不会存储重复的元素,用于存储无序(存入和取出的顺序不一定相同)元素,值不能重复。
Set集合类似于一个罐子,程序可以依次把多个对象“丢进”Set集合,而Set集合通常不能记住元素的添加顺序。实际上Set就是Collection只是行为略有不同(Set不允许包含重复元素)。
Set集合不允许包含相同的元素,如果试图把两个相同元素加入同一个Set集合中,则添加操作失败,add()方法返回false,且新元素不会被加入。
HashSet类
HashSet是Set接口的典型实现,大多数时候使用Set集合时就是使用这个实现类。
LinkedHashSet类
HashSet还有一个子类LinkedList、LinkedHashSet集合也是根据元素的hashCode值来决定元素的存储位置,但它同时使用链表维护元素的次序,这样使得元素看起来是以插入的顺序保存的,也就是说当遍历集合LinkedHashSet集合里的元素时,集合将会按元素的添加顺序来访问集合里的元素。输出集合里的元素时,元素顺序总是与添加顺序一致。但是LinkedHashSet依然是HashSet,因此它不允许集合重复。
TreeSet类
TreeSet是SortedSet接口的实现类,TreeSet可以确保集合元素处于排序状态。
TreeSet<Integer> nums = new TreeSet<>(); //向集合中添加元素 nums.add(5); nums.add(2); nums.add(15); nums.add(-4); //输出集合,可以看到元素已经处于排序状态 System.out.println(nums);//[-4, 2, 5, 15] System.out.println("集合中的第一个元素:"+nums.first());//集合中的第一个元素:-4 System.out.println("集合中的最后一个元素:"+nums.last());//集合中的最后一个元素:15 System.out.println("集合小于4的子集,不包含4:"+nums.headSet(4));//集合小于4的子集,不包含4:[-4, 2] System.out.println("集合大于5的子集:"+nums.tailSet(2));//集合大于5的子集:[2, 5, 15] System.out.println("集合中大于等于-3,小于4的子集:"+nums.subSet(-3,4));//集合中大于等于-3,小于4的子集:[2]
任务:创建一个SET集合,往集合中添加7,9,3,1,5,2,5,2,5;
1、判断集合中是否存在元素6,
2、将所有元素打印出来。
2 Map
Map 提供了一个更通用的元素存储方法。Map 集合类用于存储元素对(称作“键”和“值”),其中每个键映射到一个值
Map集合的每个元素格式: key = value (键值对元素)
- 购物车提供的商品和购买数量在后台需要容器存储
- 每个商品对象都一一对应一个购买数量
- 把每个商品对象看成是Map集合的键(key),购买数量看成是Map集合值(value)
Map集合体系结构
Map集合体系特点
1.Map集合的特点都是由键决定的
2.Map集合的键是 无序 不重复 无索引的,值可以不做要求
3.Map集合后面重复的键对应的值会覆盖前面重复键的值
4.Map集合的键值对都可以为null
代码示例:
Map<String,Integer> map = new HashMap<>(); //键 无序 不重复 无索引 值不做要求 map.put("java",10); map.put("特步",4); map.put("361",2); map.put("匹克",1); map.put(null,null); //集合里面的键值对可以都是null map.put("匹克",19);
2.1 Map集合常用API
练习:
Map<String,Integer> map = new HashMap<>(); map.put("小米",2999); map.put("华为",4999); map.put("荣耀",3999); map.put("oppo",3699); map.put("一加",3899); map.put("苹果",7999); //2.清空集合 /*map.clear(); System.out.println(map);*/ //3.判断集合是否为空 为空返回true 反之false System.out.println(map.isEmpty()); //4.根据键获取对应的值 : public V get(Object key) System.out.println(map.get("小米")); // 2999 //5.根据键删除整个元素 (删除键会返回键的值) Integer i = map.remove("苹果"); System.out.println(i); // 7999 //6.判断是否包含某个键 System.out.println(map.containsKey("华为")); //true //7.判断是否包含某个值 System.out.println(map.containsValue(100)); //true // [oppo, 华为, 一加, 荣耀, 小米] //8.获取全部键的集合 public Set<K> keySet() Set<String> strings = map.keySet(); System.out.println(strings); //9.获取全部值的集合 Collectio<V> values(); Collection<Integer> values = map.values(); System.out.println(values); //10.集合的大小 System.out.println(map.size()); // 5
Map集合的遍历
a. Map集合的遍历方式一: 键找值
// 拿到全部集合的全部键 Set<String> keys = maps.keySet(); // 遍历键, 根据键获取值 for (String key: keys) { int value = maps.get(key); System.out.println(key + "--->" +value); }
b. Map集合的遍历方式二: 键值对
// 把Map集合转成Set集合 Set<Map.Entry<String, Integer>> newMaps = maps.entrySet(); // 遍历转成的Set集合 for (Map.Entry<String, Integer> newMap : newMaps) { String key = newMap.getKey(); // 获取key Integer value = newMap.getValue(); // 获取value System.out.println(key + "--->" + value); }
c. Map集合的遍历方式三: Lambda
map.forEach((k,v)->{System.out.println(k+","+v);});
练习
1、已知某字符串,统计每个字符出现的次数。
2、任务需求:实现现实生活中的消费抽奖:
条件1:提供四类奖品,一等奖10%,二等奖20%,三等奖30%,四等奖40%。
条件2:每类奖品的数量为有限个,统一放到奖池中供抽取
条件3:每类奖品对应唯一的键值索引,根据索引值取得奖品项
条件4:每类奖品的数量被抽取一件,其总数就减少一件
(1)步骤1:创建奖项实体类 成员属性:name、count 成员方法:set/get方法 构造方法:0参2参
(2)步骤2:创建抽奖业务类 成员属性:rwdPool(Map<Integer, 奖项>) 构造方法:0参 成员方法:抽奖方法