8.集合框架
集合
一、概念:对象的容器,定义了对多个对象进行操作的常用方法。可实现类似数组的功能
二、集合和数组的区别:
(1)数组长度固定,集合长度不固定
(2)数组可以存储基本类型和引用类型,集合只能存储引用类型
三、位置:java.util.*
Collection体系

Collection父接口
-
特点:代表一组任意类型的对象,无序、无下标、不能重复。
-
创建集合
Collection collection = new ArrayList()
常用方法
- 添加元素
collection.add();
- 删除元素
collection.remove;
collection.clear;
-
遍历元素【重点】
- 使用增强for
for(Object object : collection){}- 使用迭代器
//haNext(); 有没有下一个元素 //next(); 获取下一个元素 //remove(); 删除当前元素 Iterator it = collection.iterator(); while(it.hasNext()){ String object = (String)it.next(); //强转 // 可以使用it.remove(); 进行移除元素 // collection.remove(); 不能用collection其他方法 会报并发修改异常 } -
判断
collection.contains();
collection.isEmpty();
List子接口
特点:有序、有下标、元素可以重复
方法:
1.void add(int index, Object o) //在index位置插入对象o
2.boolean addAll(int index, Collection c) //将一个集合中的元素添加到此集合的index位置
3.Object get(int index) //返回集合中指定位置的元素
4.List subList(int fromIndex, int toIndex) //返回fromIndex和toIndex之间的集合元素
public class Demo1 {
public static void main(String[] args) {
//创建集合对象
List list = new ArrayList<>();
//1.添加元素
list.add("苹果");
list.add("小米");
list.add(0,"华为");
System.out.println("元素个数"+list.toString());
//2.删除元素
//list.remove("苹果");//按元素删除
//list.remove(0);//按脚标删除
//System.out.println("删除之后"+list.toString());
//3.遍历
//3.1使用for
System.out.println("-------------------");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
//3.2使用增强for
System.out.println("-------------------");
for (Object object: list) {
System.out.println(object);
}
//3.3使用迭代器
System.out.println("-------------------");
Iterator it = list.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
//3.4使用列表迭代器ListIterator(),和Iterator()的区别:ListIterator()可以向前或向后遍历,添加、删除、修改元素
System.out.println("----------从前往后---------");
ListIterator lit = list.listIterator();
while (lit.hasNext()){
System.out.println(lit.nextIndex()+":"+lit.next());
}
System.out.println("----------从后往前---------");
while (lit.hasPrevious()){
System.out.println(lit.previousIndex()+":"+lit.previous());
}
//4.判断
System.out.println(list.contains("苹果"));
System.out.println(list.isEmpty());
//5.获取位置
System.out.println(list.indexOf("华为"));
}
}
public class Demo2 {
public static void main(String[] args) {
//创建集合
List list = new ArrayList();
//1.添加数字数据(自动装箱)
list.add(20);
list.add(30);
list.add(40);
list.add(50);
list.add(60);
System.out.println("元素个数"+list.size());
System.out.println(list.toString());
//2.删除操作
//list.remove(20);//调用remove调用的是使用脚标删除
list.remove((Object) 20);
list.remove(new Integer(30));
System.out.println("删除元素"+list.size());
System.out.println(list.toString());
//3.subList:返回子集合,含头不含尾
List sublist = list.subList(0,2);
System.out.println(sublist.toString());
}
}
List实现类
1.ArrayList【重点】
数组结构实现,查询块、增删慢
JDK1.2版本,运行效率块、线程不安全
源码分析:
(1)DEFAULT_CAPACITY = 10; 默认容量
没向集合中添加元素时,容量为0
(2)elementData 存放元素的数组
(3)size 实际的元素个数
(4)add() 添加元素
public class Demo1 {
public static void main(String[] args) {
//创建集合
ArrayList arrayList = new ArrayList<>();
//1.添加元素
Student s1 = new Student("刘德华",20);
Student s2 = new Student("郭富城",22);
Student s3 = new Student("梁朝伟",18);
arrayList.add(s1);
arrayList.add(s2);
arrayList.add(s3);
System.out.println("元素个数"+arrayList.size());
System.out.println(arrayList.toString());
//2.删除元素
// arrayList.remove(s1);//可直接使用
// arrayList.remove(new Student("郭富城",22));//重写equals后才能使用
// System.out.println("删除之后"+arrayList.size());
// System.out.println(arrayList.toString());
//3.遍历【重点】
//3.1使用迭代器
System.out.println("===================");
Iterator it = arrayList.iterator();
while (it.hasNext()){
Student s = (Student) it.next();
System.out.println(s.toString());
}
//3.2使用列表迭代器
ListIterator lit = arrayList.listIterator();
System.out.println("======从前往后=======");
while (lit.hasNext()){
Student s = (Student) lit.next();
System.out.println(s.toString());
}
System.out.println("======从后往前=======");
while (lit.hasPrevious()){
Student s = (Student) lit.previous();
System.out.println(s.toString());
}
//4.判断
System.out.println("===================");
System.out.println(arrayList.contains(s1));
System.out.println(arrayList.contains(new Student("郭富城",22)));//因为重写了equals,所以这种方式也可以
System.out.println(arrayList.isEmpty());
//5.查找
System.out.println("===================");
System.out.println(arrayList.indexOf(s1));
System.out.println(arrayList.indexOf(new Student("郭富城",22)));//因为重写了equals,所以这种方式也可以
}
}
2.Vector
数组结构实现,查询快、增删慢
JDK1.0版本,运行效率慢,线程安全
3.LinkedList【重点】
双向链表结构实现,增删快、查询慢
public class Demo1 {
public static void main(String[] args) {
//创建集合
LinkedList linkedList = new LinkedList<>();
//1.添加元素
Student s1 = new Student("刘德华",20);
Student s2 = new Student("郭富城",22);
Student s3 = new Student("梁朝伟",18);
linkedList.add(s1);
linkedList.add(s2);
linkedList.add(s3);
linkedList.add(s1);
System.out.println("元素个数:"+linkedList.size());
System.out.println(linkedList.toString());
//2.删除
//linkedList.remove(s1);
//System.out.println("删除之后:"+linkedList.size());
//linkedList.clear();
//3.遍历
//3.1for遍历
System.out.println("==========for============");
for (int i = 0; i < linkedList.size(); i++) {
System.out.println(linkedList.get(i));
}
//3.2增强for遍历
System.out.println("==========增强for=========");
for (Object object:linkedList) {
Student s = (Student) object;
System.out.println(s.toString());
}
//3.3使用迭代器
System.out.println("============迭代器=========");
Iterator it = linkedList.iterator();
while (it.hasNext()){
Student s = (Student) it.next();
System.out.println(s.toString());
}
//3.4使用列表迭代器
System.out.println("========列表迭代器=========");
ListIterator lit = linkedList.listIterator();
while (lit.hasNext()){
Student s = (Student) lit.next();
System.out.println(s.toString());
}
//4.判断
System.out.println(linkedList.contains(s1));
System.out.println(linkedList.isEmpty());
//5.获取
System.out.println(linkedList.indexOf(s1));
}
}
泛型
-
本质:参数化类型,把类型作为参数传递
-
常见的形式:泛型类、泛型接口、泛型方法
-
语法:<T,...> T称为类型占位符,表示一种引用类型
-
好处:(1)提高代码的重用性
(2)防止类型转换异常,提高代码的安全性
泛型类
- 语法:类名<>
// 写一个泛型类
public class MyGeneric<T>{
//使用泛型T
//1 创建变量
T t;
//2 泛型作为方法的参数
public void show(T t){
sout(t);
}
//3 泛型作为方法的返回值
public T getT(){
return t;
}
}
// 使用泛型类
public class TestGeneric{
public static void main(String[] args){
//使用泛型类创建对象
// 注意: 1. 泛型只能使用引用类型
// 2. 不用泛型类型对象之间不能相互赋值
MyGeneric<String> myGeneric = new MyGeneric<String>();
myGeneric.t = "hello";
myGeneric.show("hello world!");
String string = myGeneric.getT();
MyGeneric<Integer> myGeneric2 = new MyGeneric<Integer>();
myGeneric2.t = 100;
myGeneric2.show(200);
Integer integer = myGeneric2.getT();
}
}
注:(1)泛型只能是引用类型
(2)不同泛型对象不能相互赋值
(2)错误的使用方法:不能实例化,因为不知道具体是什么类型,也就不知道这个构造方法可不可以使用
T t1 = new T();//错误使用
泛型接口
- 语法:接口名
- 注意:不能泛型静态常量
-
两种使用方式:
(1)写实现类的时候直接确定好类型
public class MyInterfaceImpl implements MyInterface<String>{
public String server(String t) {
System.out.println(t);
return t;
}
}
MyInterfaceImpl impl = new MyInterfaceImpl();
impl.server("xx");
(2)实现类也变成泛型类,使用的时候再去定义
public class MyInterfaceImpl2<T> implements MyInterface<T>{
public T server(T t) {
System.out.println(t);
return null;
}
}
MyInterfaceImpl2<Integer> impl2 = new MyInterfaceImpl2<>();
impl2.server(1000);
泛型方法
- 语法:
返回值类型
public class MyGenericMethod {
public <T> void show(T t){
System.out.println("泛型方法:"+t);
}
}
MyGenericMethod myGenericMethod = new MyGenericMethod();
myGenericMethod.show("中国加油");
myGenericMethod.show(2022);
myGenericMethod.show(3.14);
泛型集合
-
概念:参数化类型、类型安全的集合,强制集合元素的类型必须一致
-
特点:
- 编译时即可检查,而非运行时抛出异常
- 访问时,不必类型转换(拆箱)
- 不同泛型之间引用不能互相赋值,泛型不存在多态
错误示范:
public class Demo3 {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList<>();
arrayList.add("xxx");
arrayList.add("yyy");
arrayList.add(10);
arrayList.add(20);
for (Object object: arrayList) {
String str = (String) object; //类型转换异常
System.out.println(str);
}
}
}
正确使用:
public class Demo3 {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add("xxx");
arrayList.add("yyy");
for (String string:arrayList) {
System.out.println(string);
}
//------------------------------------------------------------------------------
ArrayList<Student> arrayList1 = new ArrayList<Student>();
Student s1 = new Student("刘德华",20);
Student s2 = new Student("郭富城",22);
Student s3 = new Student("梁朝伟",18);
arrayList1.add(s1);
arrayList1.add(s2);
arrayList1.add(s3);
Iterator<Student> it = arrayList1.iterator();
while (it.hasNext()){
Student s = it.next();
System.out.println(s.toString());
}
}
}
Set子接口
-
特点:无序、无下标、元素不可重复
-
方法:全部继承自Collection中的方法
-
增、删、遍历、判断与Collection一致
- 注意:由于Set是无序的,没有角标,所以删除元素时不能使用角标删除,遍历时也不能使用for
Set实现类
-
HashSet【重点】
- 基于HashCode计算元素存放位置
- 基于HashCode实现元素不重复
- 当存入元素的哈希码相同时,会调用equals进行确认,如果为true,则拒绝后者存入
-
TreeSet
- 基于排列顺序实现元素不重复
HashSet
-
存储结构:哈希表(数组+链表+红黑树)
-
存储过程(重复依据)
- 根据hashCode计算保存的位置,如果位置为空,直接保存,若不为空,进行第二步
- 再执行equals方法,如果equals为true,则认为是重复,否则形成链表
-
特点:基于HashCode计算元素存放位置
- 利用31这个质数,减少散列冲突
- 31提高执行效率
31 * i = (i << 5) - i转为移位操作
- 31提高执行效率
- 当存入元素的哈希码相同时,会调用equals进行确认,如果结果为true,则拒绝后者存入
- 利用31这个质数,减少散列冲突
-
新建集合
HashSet<String> hashSet = new HashSet<String>();
- 添加元素
hashSet.add( );
- 删除元素
hashSet.remove( );
-
遍历操作
-
增强for
for( type type : hashSet) -
迭代器
Iterator<String> it = hashSet.iterator( );
-
-
判断
hashSet.contains( ); hashSet.isEmpty();
TreeSet
-
基于排列顺序实现元素不重复
-
实现了SortedSet接口,对集合元素自动排序
-
元素对象的类型必须实现Comparable接口,指定排序规则
-
通过CompareTo方法确定是否为重复元素
补充:Comparator
- Comparator:实现定制比较(比较器)
public class Demo6_TreeSet_Comparator {
public static void main(String[] args) {
//创建集合,并指定比较规则
TreeSet<Person> persons = new TreeSet<>(new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
int n1 = o1.getAge()- o2.getAge();
int n2 = o1.getName().compareTo(o2.getName());
return 0;
}
});
}
}
案例
- 要求:使用TreeSet集合实现字符串按照长度进行排序
public class Demo7_TreeSet_Test {
public static void main(String[] args) {
//创建集合,并指定比较规则
TreeSet<String> treeSet = new TreeSet<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
int n1 = o1.length() - o2.length();
int n2 = o1.compareTo(o2);
return n1==0?n2:n1;
}
});
//添加数据
treeSet.add("apple");
treeSet.add("lisi");
treeSet.add("beijing");
treeSet.add("cat");
treeSet.add("xian");
System.out.println(treeSet.toString());
}
}
Map集合
-
Map接口的特点:
- 用于存储任意键值对(key - value)
- 键:无序、无下标、不允许重复(唯一)
- 值:无序、无下标、允许重复
-
方法:
-
V put (K key,V value)//将对象存入到集合中,关联键值。key重复则覆盖原值 -
Object get(Object key)//根据键获取对应的值 -
Set<K>//返回所有key -
Collection<V> values()//返回包含所有值的Collection集合 -
Set<Map.Entry<K,V>> //键值匹配的Set集合
-
Map接口的使用

public static void main(String[] args) {
//创建Map集合
Map<String,String> map = new HashMap<>();
//1.添加元素
map.put("cn","中国");
map.put("uk","英国");
map.put("usa","美国");
map.put("cn","zhongguo");//Key重复,Value覆盖
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> keyset = map.keySet();
// for (String key:keyset) {
// System.out.println(key+"---"+map.get(key));
// }
Set<String> keyset = map.keySet();
for (String key:map.keySet()) {
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());
// }
for (Map.Entry<String,String>entry:map.entrySet()) {
System.out.println(entry.getKey()+"---"+entry.getValue());
}
//4.判断
System.out.println(map.containsKey("cn"));
System.out.println(map.containsValue("泰国"));
}
HashMap【重点】
- JDK1.2版本,线程不安全,运行效率快;允许用null作为key或是value
- 默认初始容量16,加载因子0.75
- 存储结构:数组+链表+红黑树
- 增、删、遍历、判断方法与上述一致
源码分析总结:
- HashMap刚创建时,table是null,size是0,节省空间,当添加第一个元素时,table容量调整为16
- 当元素个数大于阈值(16*0.75 = 12)时,会进行扩容,扩容后的大小为原来的两倍,目的是减少调整元素的个数
- jdk1.8 当每个链表长度 >8 ,并且数组元素个数 ≥64时,会调整成红黑树,目的是提高效率
- jdk1.8 当链表长度 <6 时 调整成链表
- jdk1.8 以前,链表时头插入,之后为尾插入
HashTable
- JDK1.0版本,线程安全,运行效率慢;不允许null作为key或是value
子类:Properties
- HashTable的子类,要求key和value都是String。通常用于配置文件的读取
TreeMap
- 实现了SortedMap接口(是map的子接口),可以对key自动排序
Collections工具类
-
概念:集合工具类,定义了除了存取以外的集合常用方法
-
sort排序
Collections.sort(list);
- binarySearch二分查找
int i = Collections.binarySearch(list,12);
System.out.println(i);
- copy复制
List<Integer> dest = new ArrayList<>();
for (int j = 0; j < list.size(); j++) {
dest.add(0);//满足大小相同,list有多少个数,dest就有多少个0
}
Collections.copy(dest,list);//dest和list大小应该相同
System.out.println(dest.toString());
- revers反转
Collections.reverse(list);
System.out.println("反转之后:"+list);
- shuffle打乱
Collections.shuffle(list);
System.out.println("打乱之后:"+list);
- 补充:
//补充1:list转成数组
System.out.println("---list转成数组---");
Integer[] arr = list.toArray(new Integer[0]);
System.out.println(arr.length);
System.out.println(Arrays.toString(arr));
//补充2:数组转成集合
System.out.println("---数组转成集合---");
String[] names = {"张三","李四","王五"};
//该集合是一个受限集合,不能添加或删除
List<String> list1 = Arrays.asList(names);
System.out.println(list1);
//把基本类型数组转成集合时,需要修改为包装类
Integer[] nums = {100,200,300,400,500};
List<Integer> list2 = Arrays.asList(nums);
System.out.println(list2);

浙公网安备 33010602011771号