day15
- 集合的概述
1.1 集合的由来
需求 : 班级有学生,Student(属性 name ,age), 有5个学生,如何存储
使用容器存储5个学生信息,定义一个学生数组
Student[] stu = new Student[5];// String[] s = new String[5]; s[i]=”abc”;
for(int i = 0 ; i < stu.length ; i ++){
stu[i] = new Student(“张三”,20);
}
需求升级 : 班级有来了2个同学
解决方法 : 从新创建一个Student[] stu = new Student[7]; 将原来数组中的5个学生信息复制过来,在添加两个
需求再升级 : 又来了3个学生…还需要重新创建更大的数组
想 : 我现在需要一个容器,装学生信息,这个容器大小如果可变话,那就符合学生添加的需求
集合----> 就是一个大小可变的容器
集合: 集合中,有一个成员变量,是一个数组,通过改变成员变量的值,就可以做到改变数组的大小,对外来说,就相当于是一个可变化的容器
int[] arr ;
arr = new int[15];
arr = new int[50];
可变容器 : 集合底层也是一个数组,初始开辟一个指定大小的数组,然后向数组中添加数据,如果数据将数组添加满了,系统底层,默认的为你分配一个更大的数组空间,原数组中内容复制到新数组中,继续向新数组中添加内容
1.2 数组与集合的区别
-
数组是定长容器,int[] arr = new int[3];
集合是可变长度容器 -
数组可以存储基本数据类型 double[] d = new double[5];
数组可以存储引用数据类型 String[] s = new String[3];
集合只能存储引用数据类型
如果客户的年龄为int类型,要存储在集合中. 实际存储在集合中,是基本数据类型对应的引用数据类型包装类 -
数组中的方法只能使用Object中继承来的方法,有一个属性length
集合是一个类,即可以使用Object中继承方法,类中自己封装了很多的方法
1.3集合的体系结构
单列集合 : 容器中,每一个元素,都是一个独立的个体
双列集合 : 容器中,一对元素,是一个整体
- Collection集合
2.1 Collection集合的介绍
Collection是一个接口, 所有单列集合的顶层的父接口,来自java.util包
Collection 兼容子接口List以及Set中的共有方法
Collection是接口,不能实例化对象,需要找一个实现类, ArrayList
// 接口的多态性, 父类(父接口)引用指向子类对象
// 父接口 coll = new 实现类对象();
Collection coll = new ArrayList();
coll调用的方法,全部都是ArrayList中的重写方法
2.2 Collection中的常用方法
- add(Object obj): 向集合中添加一个元素obj,末尾追加
代码
package com.zgjy.collectionDemo;
import java.util.ArrayList;
import java.util.Collection;
public class CollectionDemo {
public static void main(String[] args) {
// 1. 创建一个集合
Collection coll = new ArrayList();
// 2. add(Object obj)
coll.add("abc");
coll.add("123");
// ArrayList重写了父类Object中toString方法,
// 将集合中的元素打印出来
System.out.println(coll);
Collection coll2 = new ArrayList();
Student s = new Student("张三",20);
coll2.add(s);
coll2.add(new Student("李四",20));
// 如果想要将Student中的成员变量的值打印出来,那么
// 需要重写父类Object中toString方法---> alt+shift+s 自动生成
System.out.println(coll2);
}
}
package com.zgjy.collectionDemo;
public class Student {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Student() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return “Student [name=” + name + “, age=” + age + “]”;
}
}
2.remove(Object obj) : 将obj元素,从集合中删除,方法返回值类型boolean类型,如果删除成功,返回true,否则返回false
3.clear() : 清空集合,将集合中的数据,全部删除,集合仍然存在,返回值类型void
4.isEmpty() : 如果集合中没有元素,返回true,否则false ; 作用判断集合是否为空(是否有元素)
5. contains(Object obj):判断obj元素在集合中是否存在,存在返回true.不存在返回fasle,方法返回值类型boolean
代码
package com.zgjy.collectionDemo;
import java.util.ArrayList;
import java.util.Collection;
public class CollectionDemo {
public static void main(String[] args) {
//addMethod();
//removeMethod();
//clearMethod();
containsMethod();
}
// 1. add(Object obj)方法
public static void addMethod() {
// 1. 创建一个集合
Collection coll = new ArrayList();
// 2. add(Object obj)
coll.add("abc");
coll.add("123");
// ArrayList重写了父类Object中toString方法,
// 将集合中的元素打印出来
System.out.println(coll);
Collection coll2 = new ArrayList();
Student s = new Student("张三",20);
coll2.add(s);
coll2.add(new Student("李四",20));
// 如果想要将Student中的成员变量的值打印出来,那么
// 需要重写父类Object中toString方法---> alt+shift+s 自动生成
System.out.println(coll2);
}
public static void removeMethod() {
// 1. 创建一个集合
Collection coll = new ArrayList();
// 自动装箱,将int类型数据12自动封装成Integer类型
coll.add(12);
coll.add(-7);
coll.add(25);
System.out.println(coll);//[12, -7, 25]
// 2. remove(Object obj): 将obj元素,从集合中删除,方法返回值类型boolean类型,
// 如果删除成功,返回true,否则返回false
boolean boo = coll.remove(-7);
System.out.println(boo);//true
System.out.println(coll);// [12, 25]
}
public static void clearMethod() {
// 1. 创建一个集合
Collection coll = new ArrayList();
// 自动装箱,将int类型数据12自动封装成Integer类型
coll.add(12);
coll.add(-7);
coll.add(25);
System.out.println(coll);//[12, -7, 25]
// 3. isEmpty(): 如果集合中没有元素,返回true,否则false ;
//作用判断集合是否为空(是否有元素)
System.out.println(coll.isEmpty());//false
// 2. clear() :清空集合,将集合中的数据,全部删除,
// 集合仍然存在,返回值类型void
coll.clear();
System.out.println(coll);//[]
// 3. isEmpty();
System.out.println(coll.isEmpty());// true
}
public static void containsMethod() {
// 1. 创建一个集合
Collection coll = new ArrayList();
// 2. add(Object obj)
coll.add("abc");
coll.add("123");
// 3.contains(Object obj):判断obj元素在集合中是否存在,存在返回true.
//不存在返回fasle,方法返回值类型boolean
System.out.println(coll.contains("12"));// false
System.out.println(coll.contains("123"));//true
}
}
2.3 Collection中带all的方法
- addAll(Collection c) : 将集合c中的全部内容,添加到方法调用的集合末尾,返回值类型boolean
- containsAll(Collection c) : 判断方法调用的集合中,是否包含集合c中全部内容,返回值类型boolean
- removeAll(Collection c) : 将集合c中的所有的元素,从方法调用集合中删除; 获取两个集合的交集,将交集从方法调用集合删除掉
- retainAll(Collection c) : 将两个集合的交集获取到,将交集赋值给方法的调用集合
代码
package com.zgjy.collectionDemo;
import java.util.ArrayList;
import java.util.Collection;
public class CollectionAllMethod {
public static void main(String[] args) {
//1. addAll(Collection c):将集合c中的全部内容,
//添加到方法调用的集合末尾,返回值类型boolean
Collection coll1 = new ArrayList();
coll1.add("a");
coll1.add("b");
Collection coll2 = new ArrayList();
coll2.add("c");
coll2.add("d");
//2. containsAll(Collection c) : 判断方法调用的集合中,是否包含集合c中全部内容
//,返回值类型boolean
boolean boo = coll1.containsAll(coll2);
System.out.println(boo);//false
coll1.addAll(coll2);
System.out.println(coll1);
//2. containsAll(Collection c) : 判断方法调用的集合中,是否包含集合c中全部内容
//,返回值类型boolean
boolean boo1 = coll1.containsAll(coll2);
System.out.println(boo1);//true
//3. removeAll(Collection c):将集合c中的所有的元素,从方法调用集合中删除;
// 获取两个集合的交集,将交集从方法调用集合删除掉
Collection coll3 = new ArrayList();
coll3.add(1);
coll3.add(2);
Collection coll4 = new ArrayList();
coll4.add(1);
// 将coll3和coll4集合中的交集获取到 : 1
// 将交集元素1从coll3集合中删除
coll3.removeAll(coll4);
System.out.println(coll3);//[2]
// 4. retainAll(Collection c): 将两个集合的交集获取到,将交集赋值给方法的调用集合
Collection coll5 = new ArrayList();
coll5.add(1);
coll5.add(2);
Collection coll6 = new ArrayList();
coll6.add(3);
coll6.add(4);
coll5.retainAll(coll6);
System.out.println(coll5);//[]
// 4. retainAll(Collection c): 将两个集合的交集获取到,将交集赋值给方法的调用集合
Collection coll7 = new ArrayList();
coll7.add(1);
coll7.add(5);
Collection coll8 = new ArrayList();
coll8.add(1);
coll8.add(4);
coll7.retainAll(coll8);
System.out.println(coll7);//[1]
}
}
2.4 Collection第一种遍历方式
遍历 : 就是将集合中的元素一个一个的获取到
toArray() : 将集合中的所有的元素,以一个Object[]形式进行返回,返回值类型Object[]
- 为什么方法的返回值是Object[],因为集合容器中可以存储任意的引用数据类型,具体是那种类名,不明确定,那么就将父类Object进行返回
代码
package com.zgjy.collectionDemo;
import java.util.ArrayList;
import java.util.Collection;
public class CollectionBianLi1 {
public static void main(String[] args) {
Collection coll = new ArrayList();
coll.add(1);
coll.add(2);
coll.add(4);
coll.add(5);
// 1. toArray():将集合中的所有的元素,以一个Object[]形式进行返回,返回值类型Object[]
Object[] obj = coll.toArray();
for(int i = 0 ; i < obj.length ; i ++) {
Object o = obj[i];
// Integer类型是Object类型的子类,变成Integer,使用多态的向下转型
Integer in = (Integer)o;
System.out.println(in);
}
}
}
2.5 Collection第二种遍历方式–迭代器(重要)
迭代 : 更迭, 就表示从一个到下一个的过程
迭代器 : 作用就是将集合中的元素,一个一个获取到
-
迭代器的获取方法:
Collection 中方法,iterator() ,表示获取到一个集合的迭代器对象,返回值类型Iterator
Iterator 表示一个迭代器,是个接口,来自于java.util包
Iterator不能实例化对象,那么证明iterator()方法实际返回的是Iterator接口的一个实现类对象 -
迭代器中方法Iterator:
hasNext() : 问集合中还有下一个元素吗,如果有,那么返回true,如果没有,那么返回false,返回值类型boolean类型
next() : 获取当前正在迭代的元素本身,next方法,每次通过迭代器,从集合中获取一个元素,返回值类型Object类型
注意 : 如果集合中已经没有元素需要获取,继续使用next进行集合中元素获取,报错
NoSuchElementException : 没有这个元素异常
代码
package com.zgjy.collectionDemo;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionIteratorDemo {
public static void main(String[] args) {
// 1.创建一个集合
Collection c = new ArrayList();
c.add("a");
c.add("b");
c.add("c");
c.add("d");
c.add("d");
c.add("e");
// 2. 使用迭代器的方式获取集合中的元素
// 1) 先获取到集合的迭代器对象
Iterator it = c.iterator();
/*Object obj = it.next();
System.out.println(obj);
// 2) next() : 通过迭代器获取集合中的元素,next方法每次获取一个元素
System.out.println(it.next());
System.out.println(it.next());
System.out.println(it.next());
System.out.println(it.next());*/
// 3. 迭代器遍历元素升级,结合循环使用
// 1) 判断集合中是否还有元素,有元素,将元素获取到
while(it.hasNext()) {// 如果hasNext返回true,证明还有元素
//将需要获取的元素得到
System.out.println(it.next());
}
}
}
- 迭代器的工作原理:
- List集合,ArrayList,LinkedList,Vector
3.1 List集合概述
List 接口,来自于java.util包,是Collection的子接口
List接口特征:
- 有序 : 元素存入集合中的顺序,与取出的顺序保持一致
- 有索引 : 索引范围0–集合的长度-1
- 可重复 : 集合中允许存储重复元素
List接口,不能实例化对象(new对象),找实现类,ArrayList
// 多态,父接口的引用指向实现类的对象
List list = new ArrayList();
3.2 List中的特有方法
- add(int index , Object obj): 将obj元素添加到集合的指定index索引位置上
- remove(int index) : 将index索引位置上的元素删除,返回值类型Object,返回的是当前所删除的元素本身
- set(int index , Object obj) : 将index索引位置上的元素,使用obj进行替换,返回值类型Object ,返回的是被替换掉的元素本身
- get(int index) : 获取index索引位置上的元素
代码
package com.zgjy.listDemo;
import java.util.ArrayList;
import java.util.List;
public class ListMethod {
public static void main(String[] args) {
//addMethod();
//removeMethod();
//setMethod();
getMethod();
}
public static void addMethod() {
// 1. 创建一个集合
List list = new ArrayList();
// 2. add(int index,Object obj):在指定index索引位置添加元素obj
list.add(0, "a");//[a]
list.add(0, "b");//[b,a]
// 末尾追加元素
list.add("c");
list.add("d");
list.add(2, "hello");
System.out.println(list);// [b, a, hello, c, d]
}
public static void removeMethod() {
// 1. 创建一个集合
List list = new ArrayList();
// 2. add(int index,Object obj):在指定index索引位置添加元素obj
list.add(0, "a");//[a]
list.add(0, "b");//[b,a]
// 末尾追加元素
list.add("c");
list.add("d");
list.add(2, "hello");// [b, a, hello, c, d]
// 3. remove(int index):将index索引位置上的元素删除,
//返回值类型Object,返回的是当前所删除的元素本身
String s = (String)list.remove(3);
System.out.println(s);// c
System.out.println(list);// [b, a, hello, d]
}
public static void setMethod() {
List list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
// 3.set(int index , Object obj) : 将index索引位置上的元素,使用obj进行替换,
// 返回值类型Object ,返回的是被替换掉的元素本身
Object obj = list.set(2, "QQ");
System.out.println(obj);
System.out.println(list);
}
public static void getMethod() {
List list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
// 4.get(int index) : 获取index索引位置上的元素
Object obj = list.get(0);
System.out.println(obj);
Object obj1 = list.get(2);
System.out.println(obj1);
/*
* IndexOutOfBoundsException : 数组下标越界
* Object obj2 = list.get(5);
System.out.println(obj2);*/
}
}
3.3 List集合的遍历
- List可以使用迭代器进行遍历
- List可以根据索引进行遍历,索引范围0-----集合长度-1
get(int index) - 求取集合长度的方法 size() ,返回值类型int类型
- 数组求取长度 length属性
- 字符串长度 length() 方法
- 集合的长度 size() 方法
代码
package com.zgjy.listDemo;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ListFor {
public static void main(String[] args) {
// 1. 创建一个集合
List list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
// 2. 求取集合的长度
int i = list.size();
System.out.println(i);// 4
// 3. list集合的遍历,带有索引
for(int j = 0 ; j < list.size() ; j ++) {
System.out.println(list.get(j));
}
//4. 迭代器遍历
Iterator it = list.iterator();
while( it.hasNext() ) {
System.out.println("---"+it.next());
}
}
}
3.4 并发修改异常
需求 : 集合[“a”,”hello”,”b”],遍历集合,如果遇到集合中的元素为”hello”,那么向集合中添加一个元素”world”
请使用迭代器的方式实现
ConcurrentModificationException : 并发修改异常
出现异常的原因: 当通过迭代器进行集合的遍历时,一边遍历,一边向集合中添加数据,迭代器就会报出并发修改异常
并发修改异常的解决方案:
- 使用for循环方式进行集合的遍历,不会发生并发修改异常
原因 : 每次for循环都会重新的调用list.size方法,如果集合的大小改变,list.size跟着变化 - List中的方法 listIterator(), 返回值类型为ListIterator
ListIterator 接口,也是一种迭代器,当从一个方向进行集合遍历时,允许在遍历的同时,向集合中添加元素
ListIterator 中的方法:
- hasNext() : 判断集合中,是否有下一个元素,如果有元素,返回true,没有元素返回false
- next() : 获取集合中正在被迭代的元素
- add(Object obj) : 通过迭代器向集合中添加元素
代码
package com.zgjy.listDemo;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class ListException {
public static void main(String[] args) {
//addEle();
ListIteratorMethod();
}
/*
* 需求 : 集合[“a”,”hello”,”b”],遍历集合,
* 如果遇到集合中的元素为”hello”,
* 那么向集合中添加一个元素”world”
*
* */
public static void addEle() {
List list = new ArrayList();
list.add(“a”);
list.add(“hello”);
list.add(“b”);
System.out.println(list);//[a, hello, b]
// 1. for循环解决并发修改异常
for(int i = 0 ; i < list.size() ; i ++) {
String s = (String)list.get(i);
if("hello".equals(s)) {
list.add("world");
}
}
System.out.println(list);//[a, hello, b, world]
// 使用迭代器进行遍历
// 1) 获取到集合的迭代器对象
// 发生了并发修改异常,
Iterator it = list.iterator();
while( it.hasNext() ) {
Object obj = it.next();
String s = (String)obj;
if("hello".equals(s)) {
list.add("world");
}
}
System.out.println(list);
}
public static void ListIteratorMethod() {
List list = new ArrayList();
list.add("a");
list.add("hello");
list.add("b");
// 通过listIterator获取到ListIterator迭代器
/*ListIterator 接口,也是一种迭代器,当从一个方向进行集合
* 遍历时,允许在遍历的同时,向集合中添加元素,解决并发修改问题
*/
ListIterator it = list.listIterator();
while(it.hasNext()) {
Object obj = it.next();
String s = (String)obj;
if("hello".equals(s)) {
//使用ListIterator中的方法add向集合中添加元素
it.add("world");
}
}
System.out.println(list);
}
}
3.5 List的实现类
ArrayList : 底层数组结构,查询快,增删慢
LinkedList : 底层链表结构,查询慢,增删快
Vector : 从JDK1.2版本,被ArrayList取代, 底层数组结构,查询慢,增删慢
ArrayList数据结构:
LinkedList 数据结构:
分析:
实际开发场景中,ArrayList使用最多,直接ArrayList a = new ArrayList();
因为真正的开发场景,查询多于增删