18_集合
一. 集合
- 概念:对象的容器,定义了对多个对象进行操作的常用方法。可实现数组的功能
- 和数组区别
- 数组长度固定,集合长度不固定
- 数组可以存储基本类型和引用类型,集合只能存储引用类型
- 位置:java.util.*;
Collection体系集合
Interface Collection | ||||
---|---|---|---|---|
Interface List | Interface Set | |||
Class ArrayList | Class LinkedList | Class Vector | Class HashSet | Interface SortedSet |
Class TreeSet |
- 该体系结构的根接口,代表一组对象,称为集合
- List接口的特点
- 有序、有下标、元素可重复
- Set接口的特点
- 无序、无下标、元素不能重复
1. Collection接口
特点:代表一组任意类型的对象,无序、无下标、不能重复
方法:
boolean add(Object obj)//1. 添加一个对象 boolean addAll(Collection c)//2. 将一个集合中的所有对象添加到此集合中 void clear()//3. 清空此集合中的所有对象 boolean contains(Object o)//4. 检查此集合中是否包含o对象 boolean equals(Object o)//5. 比较此集合是否与指定对象相等 boolean isEmpty()//6. 判断此集合是否为空 boolean remove(Object o)//7. 在此集合中移除o对象 int size()//8. 返回此集合中元素的个数 Object[] toArray()//9. 将此集合转换成数组 //创建集合 Collection collection = new ArrayList(); //1. 添加元素 collection.add("苹果"); collection.add("西瓜"); collection.add("香蕉"); System.out.println("元素个数:" + collection.size()); System.out.println(collection); // //2. 删除元素 // collection.remove("西瓜"); // collection.clear(); // System.out.println("元素个数:" + collection.size()); //3. 遍历元素(重点) //3.1 使用增强for for (Object object : collection) { System.out.println(object); } //3.2 使用迭代器(专门用来遍历集合的一种方式) //hasNext()有没有下一个元素 //next()获取下一个元素 //remove()删除当前元素 System.out.println("----------"); Iterator iter = collection.iterator(); while (iter.hasNext()){ String s = (String)iter.next(); System.out.println(s); //迭代过程中无法使用collection的remove()方法 //iter.remove(); } System.out.println("元素个数:" + collection.size()); //4. 判断 System.out.println(collection.contains("西瓜")); System.out.println(collection.isEmpty());
2. List接口与实现类
List接口
特点:有序、有下标、元素可以重复
方法:
void add(int index, Object o)//1. 在index位置插入对象o boolean addAll(int index, Collection c)//2. 将一个集合中的元素添加到此集合中的index位置 Object get(int index)//3. 返回集合中指定位置的元素 List subList(int fromIndex, int toIndex)//4. 返回fromIndex和toIndex之间的集合元素 //1. 添加元素 List list = new ArrayList(); list.add("手机"); list.add("耳机"); list.add(0,"电脑");//将电脑放在下标为0 的位置 System.out.println("元素个数:" + list.size()); System.out.println(list.toString());//电脑 手机 //2. 删除元素 list.remove("耳机"); System.out.println("删除后的元素个数:" + list.size()); System.out.println(list.toString()); //3. 遍历 //3.1 使用for遍历 System.out.println("----------3.1使用for遍历--------"); for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } //3.2 使用增强for System.out.println("----------3.2使用增强for--------"); for (Object o : list) { System.out.println(o); } //3.3 使用迭代器iterator System.out.println("----------3.3使用迭代器iterator--------"); Iterator iter = list.iterator(); while (iter.hasNext()){ System.out.println(iter.next()); } //3.4 使用列表迭代器listIterator,可以向前,向后遍历,添加修改删除元素 System.out.println("----------3.4使用列表迭代器listIterator从前往后--------"); ListIterator listIterator = list.listIterator(); while (listIterator.hasNext()){ //0:电脑 //1:手机 System.out.println(listIterator.nextIndex() + ":" + listIterator.next()); } System.out.println("----------3.4使用列表迭代器listIterator从后往前--------"); while (listIterator.hasPrevious()){ //1:手机 //0:电脑 System.out.println(listIterator.previousIndex() + ":" + listIterator.previous()); } //4. 判断 System.out.println(list.contains("电脑")); System.out.println(list.isEmpty()); //5. 获取位置 System.out.println(list.indexOf("电脑")); //6.subList返回子集合,含头不含尾 List sublist = list.subList(0,1); System.out.println(sublist.toString());//[电脑]
List实现类
(1) ArrayList
ArrayList【重点】:
- 数组结构实现,查询快、增删慢
- JDK1.2版本,运行效率快、线程不安全
- 源码分析:
- 默认容量 DEFAULT_CAPACITY = 10;(还未向集合中添加任何元素时,容量为0,添加任意元素后,容量为10,每次扩容为原来的1.5倍)
- 存放元素的数组 elementData
- 实际元素个数 size
//创建集合 ArrayList ArrayList arrayList = new ArrayList(); //1. 添加元素 Student s1 = new Student("张三", 18); Student s2 = new Student("李四", 19); Student s3 = new Student("王五", 20); arrayList.add(s1); arrayList.add(s2); arrayList.add(s3); System.out.println("元素个数:" + arrayList.size()); System.out.println(arrayList.toString()); // //2. 删除元素 // arrayList.remove(0);//删除下标为0的s1 // arrayList.remove(s2);//删除s2 // System.out.println(arrayList.toString()); // // arrayList.remove(new Student("王五",20));//equals(this == obj) // System.out.println(arrayList.size()); //3. 遍历元素【重点】 //3.1 使用迭代器 System.out.println("-------3.1 使用迭代器-------"); Iterator iter = arrayList.iterator(); while (iter.hasNext()){ Student s = (Student)iter.next(); System.out.println(s.toString()); } //3.2 使用列表迭代器 System.out.println("-------3.2 使用列表迭代器正序-------"); ListIterator lit = arrayList.listIterator(); while (lit.hasNext()){ Student s = (Student)lit.next(); System.out.println(s.toString()); } //3.2 使用列表迭代器 System.out.println("-------3.2 使用列表迭代器逆序-------"); while (lit.hasPrevious()){ Student s = (Student) lit.previous(); System.out.println(s.toString()); } //4. 判断 System.out.println(arrayList.contains(s1)); System.out.println(arrayList.isEmpty()); //5. 查找 System.out.println(arrayList.indexOf(s2));
(2) Vector
- Vector:
- 数组结构实现,查询快、增删慢
- JDK1.0版本,运行效率慢、线程安全
//创建集合 Vector Vector vector = new Vector(); vector.add("苹果"); vector.add("香蕉"); vector.add("橘子"); //Vector用法与ArrayList基本一致,但遍历时,ArrayList用的是列表迭代器,Vector则是是枚举方法Enumeration Enumeration enumeration = vector.elements(); while (enumeration.hasMoreElements()){ String s = (String)enumeration.nextElement(); System.out.println(s); }
(3) LinkedList
- LinkedList :
- 链表结构实现,查询慢、增删快
- 用法与ArrayList基本一致
3. 泛型和工具类
- java泛型是JDK1.5中引入的一个新特性,其本质是参数化类型、把类型作为参数传递,类型安全的集合、强制集合元素的类型必须一致
- 常见形式有泛型类、泛型接口、泛型方法
- 语法:<T,...> T称为类型占位符,表示一种引用类型
- 好处:
- 提高代码的复用性
- 编译时即可检查,而非运行时抛出异常
- 访问时,不必类型转换(拆箱),防止类型转换异常,提高代码的安全性
- 注意:不同泛型之间引用不能相互赋值,泛型不存在多态
(1)泛型类
public class MyGeneric<T> { //使用泛型T,T表示类型占位符,表示一种引用类型,如使用多个用逗号隔开 //创建变量 T t; //2. 泛型作为方法的参数 public void show(T t){ System.out.println(t); } //3. 泛型作为方法的返回值 public T getT(){ return t; } }
(2)泛型接口
//注意:不能泛型静态常量 public interface MyInterface<T> { String name = "张三"; T server(T t); }
泛型接口的实现类写法一(泛型接口的类型确定)
public class MyInterfaceIMPL implements MyInterface<String> { @Override public String server(String t) { System.out.println(t); return t; } }
泛型接口的实现类写法二(泛型接口的类型不确定,泛型类的类型也不确定)
public class MyInterfaceIMPL2<T> implements MyInterface<T>{ @Override public T server(T t) { System.out.println(t); return t; } }
(3)泛型方法
(语法: 返回值类型)
public class MyGenericMethod { //泛型方法 public <T> T show(T t){ System.out.println("泛型方法"); System.out.println(t); return t; } }
代码运行测试
public class TestGeneric { public static void main(String[] args) { //使用泛型类创造对象 //1. 泛型只能使用引用类型 2. 不同泛型类型对象之间不能相互赋值 MyGeneric<String> myGeneric = new MyGeneric<String>() ; myGeneric.show("大家好,加油!");//大家好,加油! myGeneric.t = "hello"; String string = myGeneric.getT(); System.out.println(string);//hello MyGeneric<Integer> myGeneric1 = new MyGeneric<Integer>(); myGeneric1.show(123); myGeneric1.t = 456; Integer integer = myGeneric1.getT(); System.out.println(integer); //泛型接口的使用 MyInterfaceIMPL impl = new MyInterfaceIMPL(); System.out.println(impl.name); impl.server("aaa"); // MyInterface<String> im = new MyInterfaceIMPL(); // System.out.println(im.name); // im.server("sss"); MyInterfaceIMPL2<Integer> impl2 = new MyInterfaceIMPL2<Integer>(); impl2.server(111); //泛型方法 MyGenericMethod method = new MyGenericMethod(); method.show("s"); method.show(123); } }
4. Set接口与实现类
- 特点:无序、无下标、元素不可重复
- 方法:全部继承自Collection中的方法
Set接口
//创建集合 Set<String> set = new HashSet<>(); //1. 添加数据 set.add("小米"); set.add("大米"); set.add("黑米"); set.add("糙米"); //set.add("黑米"); System.out.println("元素个数:" + set.size()); System.out.println(set.toString()); //2. 删除数据 set.remove("黑米"); System.out.println(set.toString()); //3. 遍历(重点) //3.1 增强for for (String s : set) { System.out.println(s); } //3.2 迭代器 Iterator<String> iter = set.iterator(); while (iter.hasNext()){ String s = iter.next(); System.out.println(s); } //4. 判断 System.out.println(set.contains("大米")); System.out.println(set.isEmpty());
(1)HashSet
- 基于HashCode计算元素存放位置
- 当存入元素的哈希码相同时,会调用equals进行确认,如结果为true,则拒绝后者存入
//创建集合 HashSet<Person> person = new HashSet<>(); //1. 添加数据 Person s1 = new Person("唐三", 18); Person s2 = new Person("小舞", 18); Person s3 = new Person("唐昊", 38); person.add(s1); person.add(s2); person.add(s3); person.add(new Person("唐三", 18));//因为重写了HashCode和equals方法,所以未能添加成功 System.out.println("学生个数" + person.size()); System.out.println(person.toString()); //2. 删除数据 person.remove(s3); System.out.println("学生个数" + person.size()); //3. 遍历数据 //3.1 增强for for (Person person1 : person) { System.out.println(person1); } //3.2 迭代器 Iterator<Person> iter = person.iterator(); while (iter.hasNext()){ Person person1 = iter.next(); System.out.println(person1); } //4. 判断 //因为重写了HashCode和equals方法,所以返回true System.out.println(person.contains(new Person("唐三", 18)));//true
重写了hashcode和的equals方法
@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return age == person.age && Objects.equals(name, person.name); } @Override public int hashCode() { return Objects.hash(name, age); }
(2)TreeSet
- 基于排列顺序实现元素不重复
- 实现了SortedSet接口,对集合元素自动排序
- 元素对象的类型必须实现Comparable接口,指定排序规则
- 通过CompareTo方法确定是否为重复元素
//要求:元素必须实现Comparable接口,CompareTo方法的返回值为0,认为是重复元素 //创建集合 TreeSet<Person> person = new TreeSet<>(); //1. 添加元素 Person s1 = new Person("张三", 18); Person s2 = new Person("李四", 19); Person s3 = new Person("王五", 20); Person s4 = new Person("王五", 25); person.add(s1); person.add(s2); person.add(s3); person.add(s4); System.out.println("元素个数:" + person.size()); System.out.println(person.toString()); //2. 删除 person.remove(new Person("王五", 25)); System.out.println(person.toString()); //3. 遍历 //3.1 增强for for (Person person1 : person) { System.out.println(person1); } //3.2 迭代器 Iterator<Person> iter = person.iterator(); while (iter.hasNext()){ Person p = iter.next(); System.out.println(p); } //4. 判断 System.out.println(person.contains(s1)); System.out.println(person.contains(new Person("王五", 25))); System.out.println(person.isEmpty());
Person类实现了Comparable接口
//先按姓名比,再按年龄比 @Override public int compareTo(Person o) { int n1 = this.getName().compareTo(o.getName()); int n2 = this.getAge()-o.getAge(); return n1==0?n2:n1; }
使用TreeSet集合实现字符串按照长度进行排序
package com.collection.Set; import java.util.Comparator; import java.util.TreeSet; /** * * @description: 使用TreeSet集合实现字符串按照长度进行排序 */ public class Demo06 { public static void main(String[] args) { TreeSet<String> treeSet = new TreeSet<>(new Comparator<String>() { @Override public int compare(String o1, String o2) { int i1 = o1.length()-o2.length(); int i2 = o1.compareTo(o2); return i1==0?i2:i1; } }); treeSet.add("zhangsan"); treeSet.add("lisi"); treeSet.add("wangwu"); treeSet.add("liuliu"); treeSet.add("beijing"); treeSet.add("shanghai"); System.out.println(treeSet.toString()); } }
5. Map接口与实现类
Map接口
特点:
- 用于存储任意键值对(Key-Value)
- 键:无序、无下标、不允许重复(唯一)
- 值:无序、无下标、允许重复
Interface Map | |
---|---|
Class HashMap | Interface SortedMap |
Class TreeMap |
方法:
V put(K key,V value)//将对象存入到集合中,关联键值。Key重复则覆盖原值 Object get(Object key)//根据键获取对应的值 Set<K>//返回所有Key Collection<V> values()//返回包含所有值的Collecton集合 Set<Map.Entry<K,V>>//键值匹配的Set集合 //创建Map集合 Map<String, String> map = new HashMap<>(); //1. 添加元素 map.put("cn", "中国"); map.put("usa", "美国"); map.put("ck", "英国"); //map.put("ck", "yingguo");//会给cn重新赋值 System.out.println("元素个数:" + map.size()); System.out.println(map.toString()); //2. 删除 map.remove("usa"); System.out.println(map.size()); //3. 遍历 //3.1 使用keySet()方法 System.out.println("-------使用keySet()方法-----------"); Set<String> keys = map.keySet(); for (String key : keys) { System.out.println(key + map.get(key)); } //3.2 使用entrySet()方法 System.out.println("-------使用entrySet()方法-----------"); Set<Map.Entry<String, String>> entries = map.entrySet(); for (Map.Entry<String, String> entry : entries) { System.out.println(entry.getKey() + entry.getValue()); } //4. 判断 System.out.println(map.containsKey("cn")); System.out.println(map.containsValue("中国"));
(1)HashMap
- HashMap【重点】
- JDK1.2版本,线程不安全,运行效率快;允许用null作为key或是value
//创建集合 //刚创建HashMap还没有添加元素时,table=null size=0 目的:节省空间 HashMap<Teacher, String> teacher = new HashMap<Teacher, String>(); //1. 添加元素 Teacher s1 = new Teacher("唐三", 18); Teacher s2 = new Teacher("小舞", 19); Teacher s3 = new Teacher("小奥", 20); teacher.put(s1, "北京"); teacher.put(s2, "上海"); teacher.put(s3, "广州"); teacher.put(new Teacher("唐三", 18), "西安");//因为重写了HashCode和equals方法,所以未能添加 System.out.println("元素个数" + teacher.size()); System.out.println(teacher.toString()); //2. 删除数据 teacher.remove(s3); System.out.println("学生个数" + teacher.size()); //3. 遍历数据 //3.1 keySet Set<Teacher> keys = teacher.keySet(); for (Teacher key : keys) { System.out.println(key + teacher.get(key)); } //3.2 entrySet Set<Map.Entry<Teacher, String>> entries = teacher.entrySet(); for (Map.Entry<Teacher, String> entry : entries) { System.out.println(entry.getKey() + entry.getValue()); } //4. 判断 //因为重写了HashCode和equals方法,所以返回true System.out.println(teacher.containsKey(s1));//true System.out.println(teacher.containsKey(new Teacher("小奥", 20)));//true
源码总结:
- HashMap 刚创建时,table是null,为了节省空间,当添加第一个元素时,table容量调整为16
- 当元素个数大于阈值(16*0.75=12)时,会进行扩容,扩容后大小为原来的2倍。目的是减少调整元素的个数
- jdk1.8 当每个链表长度大于8,并且数组元素个数大于等于64时,会调整为红黑树,目的提高执行效率
- jdk1.8 当链表长度小于6时,调整成链表
- jdk1.8以前,链表是头插入,jdk1.8以后是尾插入
Hashtable:
jdk1.0版本,线程安全,运行效率慢;不允许null作为key或是value
Properties:
Hashtable的子类,要求Key和value 都是String。通常用于配置文件的读取
(2)TreeMap
- 实现了SortedMap接口(Map的子接口),可以对Key自动排序
//要求:元素必须实现Comparable接口,CompareTo方法的返回值为0,认为是重复元素 TreeMap<Teacher, String> treeMap = new TreeMap<>(); //1. 添加元素 Teacher s1 = new Teacher("唐三", 21); Teacher s2 = new Teacher("小舞", 23); Teacher s3 = new Teacher("小奥", 20); treeMap.put(s1, "aaa"); treeMap.put(s2, "bbb"); treeMap.put(s3, "ccc"); treeMap.put(new Teacher("小奥",20), "ddd"); System.out.println("元素个数:" + treeMap.size()); System.out.println(treeMap.toString()); //2.删除 treeMap.remove(new Teacher("小奥",20)); System.out.println("元素个数:" + treeMap.size()); //3. 遍历 //3.1 使用keySet Set<Teacher> keys = treeMap.keySet(); for (Teacher key : keys) { System.out.println(key + "-----" + treeMap.get(key)); } //3.2 使用entrySet Set<Map.Entry<Teacher, String>> entries = treeMap.entrySet(); for (Map.Entry<Teacher, String> entry : entries) { System.out.println(entry.getKey() + "-----" + entry.getValue()); } //判断 System.out.println(treeMap.containsKey(new Teacher("小舞", 23)));
6.Collections工具类
概念:集合工具类,定义了除了存取以外的集合常用方法
方法:
public static void reverse(List<?> list)//反转集合中元素的顺序 public static void shuffle(List<?> list)//随机重置集合元素的顺序 public static void sort(List<T> list)//升序排序(元素类型必须实现Comparable接口) List<Integer> list = new ArrayList<>(); list.add(8); list.add(5); list.add(6); //sort排序 System.out.println("排序前:" + list.toString());//[8, 5, 6] Collections.sort(list); System.out.println("排序后:" + list.toString());//[5, 6, 8] //binarySearch二分查找 int i = Collections.binarySearch(list, 6); System.out.println(i);//1 //copy复制,现集合长度需要和被复制集合长度一致 List<Integer> dest = new ArrayList<>(); for (int j = 0; j < list.size(); j++) { dest.add(0); } Collections.copy(dest, list); System.out.println(dest.toString());//[5, 6, 8] //reverse反转 Collections.reverse(list); System.out.println("反转后:" + list.toString());//[8, 5, 6] //shuffle 打乱 Collections.shuffle(list); System.out.println("打乱后:" + list.toString());//[5, 8, 6] 随机排序 //补充:list转数组 Integer[] arr = list.toArray(new Integer[5]); System.out.println(arr.length); System.out.println(Arrays.toString(arr)); //数组转集合 String[] names = new String[]{"aa","bb","cc"}; //此时的集合是受限集合,不能添加和删除 List<String> list2 = Arrays.asList(names); System.out.println(list2); //基本类型数组转成集合时,需要修改为包装类 Integer[] nums = {10, 20, 30}; List<Integer> list3 = Arrays.asList(nums); System.out.println(list3);
二. 集合总结
- 集合的概念
- 对象的容器,和数组类似,定义了对多个对象进行操作的常用方法
- List集合
- 有序、有下标、元素可以重复。(ArrayList、LinkList、Vector)
- Set集合
- 无序、无下标、元素不可重复。(HashSet,TreeSet)
- Map集合
- 存储一对数据,无序、无下标、键不可重复,值可重复、(HashMap、HashTable、TreeMap)
- Collections
- 集合工具类,定义了除存取以外的集合常用方法
本文作者:qimu666
本文链接:https://www.cnblogs.com/qimu666/p/16565597.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步