课堂知识点
一、单列集合体系结构
1.什么是单列集合
? 单列集合一次只能存储一个元素
2.Collection接口
? 是单列集合最顶层的接口。提供了一些特别共性的方法。只要是单列集合实现类,都可以使用这些方法
3.单列集合体系图
? 
4.Collection接口中的常用方法
- 方法分类
| 方法名 | 说明 |
|---|---|
| boolean add(E e) | 向集合中添加一个元素 |
| void clear() | 清空集合所有元素 |
| boolean remove(E e) | 删除某个元素 |
| boolean contains(E e) | 判断集合中是否包含指定元素 |
| boolean isEmpty() | 判断集合是否为空 |
| int size() | 获取集合的长度 |
| Object[] toArray() | 将集合转换为一个数组 |
-
示例代码
public class Demo01Collection { public static void main(String[] args) { //创建集合对象,可以使用多态 Collection<String> coll = new ArrayList<>(); //Collection<String> coll = new HashSet<>(); System.out.println(coll);//重写了toString方法 [] /* public boolean add(E e): 把给定的对象添加到当前集合中 。 返回值是一个boolean值,一般都返回true,所以可以不用接收 */ boolean b1 = coll.add("张三"); System.out.println("b1:"+b1);//b1:true System.out.println(coll);//[张三] coll.add("李四"); coll.add("李四"); coll.add("赵六"); coll.add("田七"); System.out.println(coll);//[张三, 李四, 赵六, 田七] /* public boolean remove(E e): 把给定的对象在当前集合中删除。 返回值是一个boolean值,集合中存在元素,删除元素,返回true 集合中不存在元素,删除失败,返回false */ boolean b2 = coll.remove("赵六"); System.out.println("b2:"+b2);//b2:true boolean b3 = coll.remove("赵四"); System.out.println("b3:"+b3);//b3:false System.out.println(coll);//[张三, 李四, 田七] /* public boolean contains(E e): 判断当前集合中是否包含给定的对象。 包含返回true 不包含返回false */ boolean b4 = coll.contains("李四"); System.out.println("b4:"+b4);//b4:true boolean b5 = coll.contains("赵四"); System.out.println("b5:"+b5);//b5:false //public boolean isEmpty(): 判断当前集合是否为空。 集合为空返回true,集合不为空返回false boolean b6 = coll.isEmpty(); System.out.println("b6:"+b6);//b6:false //public int size(): 返回集合中元素的个数。 int size = coll.size(); System.out.println("size:"+size);//size:3 //public Object[] toArray(): 把集合中的元素,存储到数组中。 Object[] arr = coll.toArray(); for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } //public void clear() :清空集合中所有的元素。但是不删除集合,集合还存在 coll.clear(); System.out.println(coll);//[] System.out.println(coll.isEmpty());//true } }
二、迭代器
1.Iterator接口
- 迭代器是一种通用的遍历集合的方式
- hasNext():判断迭代器中是否还有元素
- next():获取迭代器中的元素
2.如何获取迭代器对象
- 通过集合的方法:iterator()获取迭代器对象
- 使用hasNext()方法来判断是否还有元素
- 如果有元素,通过next()方法获取出当前元素
3.通过迭代器遍历集合
public class Demo01Iterator {
public static void main(String[] args) {
//创建一个集合对象
Collection<String> coll = new ArrayList<>();
//往集合中添加元素
coll.add("姚明");
coll.add("科比");
coll.add("麦迪");
coll.add("詹姆斯");
coll.add("艾弗森");
/*
1.使用集合中的方法iterator()获取迭代器的实现类对象,使用Iterator接口接收(多态)
注意:
Iterator<E>接口也是有泛型的,迭代器的泛型跟着集合走,集合是什么泛型,迭代器就是什么泛型
*/
//多态 接口 实现类对象
Iterator<String> it = coll.iterator();
/*
发现使用迭代器取出集合中元素的代码,是一个重复的过程
所以我们可以使用循环优化
不知道集合中有多少元素,使用while循环
循环结束的条件,hasNext方法返回false
*/
while(it.hasNext()){
String e = it.next();
System.out.println(e);
}
}
}
4.迭代器实现原理

5.迭代器的并发修改异常
-
出现原因
- 在使用迭代器进行遍历过程中,又对集合的元素进行修改。抛出:ConcurrentModificationException
-
解决方式
- 不要在遍历的时候修改集合元素
- 采用ListIterator迭代器。调用迭代器本身的修改方法。修改迭代器中的映射副本后,会自动同步到集合中
-
示例代码
public class Demo02Iterator { public static void main(String[] args) { //创建一个集合对象 List<String> coll = new ArrayList<>(); //往集合中添加元素 coll.add("姚明"); coll.add("科比"); coll.add("麦迪"); coll.add("詹姆斯"); coll.add("艾弗森"); //使用Collection接口中的方法iterator获取一个迭代器 Iterator<String> it = coll.iterator(); //使用Iterator接口中的方法hasNext和next取出集合中的元素 while (it.hasNext()){ String s = it.next(); System.out.println(s); /* 增加一个判断,如果集合中有科比 增加一个元素 奥尼尔 */ if("科比".equals(s)){ //coll.add("奥尼尔"); } } System.out.println("------------------------------"); ListIterator<String> lit = coll.listIterator(); while(lit.hasNext()){ String s = lit.next(); System.out.println(s); /* 增加一个判断,如果集合中有科比 增加一个元素 奥尼尔 */ if("科比".equals(s)){ lit.add("奥尼尔"); } } System.out.println(coll);//[姚明, 科比, 奥尼尔, 麦迪, 詹姆斯, 艾弗森] } }
三、增强for循环
1.定义格式
for(容器元素的数据类型 变量名 : 容器对象名) {
循环体;
}
2.作用
-
可以遍历数组或集合
public class Demo03Foreach { public static void main(String[] args) { demo02(); } //使用增强for循环遍历集合 private static void demo02() { ArrayList<String> list = new ArrayList<>(); list.add("aaa"); list.add("bbb"); list.add("ccc"); list.add("ddd"); for (String s : list) { System.out.println(s); } } //使用增强for循环遍历数组 private static void demo01() { int[] arr = {1,2,3,4,5}; for(int i:arr){ System.out.println(i); } } }
四、泛型
1.什么是泛型
? 指的是一种广泛的数据类型。当我们在定义的时候不确定使用什么数据类型,就可以采用泛型。
? 在创建对象使用时,就可以确定具体的数据类型!
2.泛型的好处
- 可以明确约束容器中存储的数据的数据类型
- 可以不用转型了
3.定义泛型类
-
泛型类
public class MyClass<T> { public void print(T str) { System.out.println(str); } } -
测试类
public class Test02 { public static void main(String[] args) { MyClass<String> my1 = new MyClass<>(); my1.print("hello"); MyClass<Integer> my2 = new MyClass(); my2.print(10); MyClass<Double> my3 = new MyClass<>(); my3.print(5.5); } }
4.定义泛型方法
-
泛型方法的类
public class GenericMethod { //定义一个含有泛型的方法 public <M> void method01(M m){ System.out.println(m); } //定义一个含有泛型的静态方法 public static <S> void method02(S s){ System.out.println(s); } } -
测试类
public class Demo03GenericMethod { public static void main(String[] args) { //创建GenericMethod对象 GenericMethod gm = new GenericMethod(); /* 调用含有泛型的方法method01 传递什么类型,泛型就是什么类型 */ gm.method01(10); gm.method01("abc"); gm.method01(8.8); gm.method01(true); gm.method02("静态方法,不建议创建对象使用"); //静态方法,通过类名.方法名(参数)可以直接使用 GenericMethod.method02("静态方法"); GenericMethod.method02(1); } }
5.定义泛型接口
-
泛型接口
public interface GenericInterface<I> { public abstract void method(I i); } -
实现类1
public class GenericInterfaceImpl1 implements GenericInterface<String>{ @Override public void method(String s) { System.out.println(s); } } -
实现类2
public class GenericInterfaceImpl2<I> implements GenericInterface<I> { @Override public void method(I i) { System.out.println(i); } } -
测试类
public class Demo04GenericInterface { public static void main(String[] args) { //创建GenericInterfaceImpl1对象 GenericInterfaceImpl1 gi1 = new GenericInterfaceImpl1(); gi1.method("字符串"); //创建GenericInterfaceImpl2对象 GenericInterfaceImpl2<Integer> gi2 = new GenericInterfaceImpl2<>(); gi2.method(10); GenericInterfaceImpl2<Double> gi3 = new GenericInterfaceImpl2<>(); gi3.method(8.8); } }
6.泛型通配符
-
通配符
public class Demo05Generic { public static void main(String[] args) { ArrayList<Integer> list01 = new ArrayList<>(); list01.add(1); list01.add(2); ArrayList<String> list02 = new ArrayList<>(); list02.add("a"); list02.add("b"); printArray(list01); printArray(list02); //ArrayList<?> list03 = new ArrayList<?>(); } /* 定义一个方法,能遍历所有类型的ArrayList集合 这时候我们不知道ArrayList集合使用什么数据类型,可以泛型的通配符?来接收数据类型 注意: 泛型没有继承概念的 */ public static void printArray(ArrayList<?> list){ //使用迭代器遍历集合 Iterator<?> it = list.iterator(); while(it.hasNext()){ //it.next()方法,取出的元素是Object,可以接收任意的数据类型 Object o = it.next(); System.out.println(o); } } } -
向上限定
? extends E 只能传递E类型本身或者E类型的子类
-
向下限定
? super E 只能传递E类型本身或者E类型的父类
-
示例代码
public class Demo06Generic { public static void main(String[] args) { Collection<Integer> list1 = new ArrayList<>(); Collection<String> list2 = new ArrayList<>(); Collection<Number> list3 = new ArrayList<>(); Collection<Object> list4 = new ArrayList<>(); getElement1(list1); //getElement1(list2);//报错 getElement1(list3); //getElement1(list4);//报错 //getElement2(list1);//报错 //getElement2(list2);//报错 getElement2(list3); getElement2(list4); /* 类与类之间的继承关系 Integer extends Number extends Object String extends Object */ } // 泛型的上限:此时的泛型?,必须是Number类型或者Number类型的子类 public static void getElement1(Collection<? extends Number> coll){} // 泛型的下限:此时的泛型?,必须是Number类型或者Number类型的父类 public static void getElement2(Collection<? super Number> coll){} }
五、斗地主案例
public class DouDiZhu {
public static void main(String[] args) {
//1.准备牌
//定义一个存储54张牌的ArrayList集合,泛型使用String
ArrayList<String> poker = new ArrayList<>();
//定义两个数组,一个数组存储牌的花色,一个数组存储牌的序号
String[] colors = {"?","?","?","?"};
String[] numbers = {"2","A","K","Q","J","10","9","8","7","6","5","4","3"};
//先把大王和小王存储到poker集合中
poker.add("大王");
poker.add("小王");
//循环嵌套遍历两个数组,组装52张牌
for(String number : numbers){
for (String color : colors) {
//System.out.println(color+number);
//把组装好的牌存储到poker集合中
poker.add(color+number);
}
}
//System.out.println(poker);
/*
2.洗
使用集合的工具类Collections中的方法
static void shuffle(List<?> list) 使用默认随机源对指定列表进行置换。
*/
Collections.shuffle(poker);
//System.out.println(poker);
/*
3.发
*/
//定义4个集合,存储玩家的牌和底牌
ArrayList<String> player01 = new ArrayList<>();
ArrayList<String> player02 = new ArrayList<>();
ArrayList<String> player03 = new ArrayList<>();
ArrayList<String> diPai = new ArrayList<>();
/*
遍历poker集合,获取每一张牌
使用poker集合的索引%3给3个玩家轮流发
剩余3张牌给底牌
注意:
先判断底牌(i>=51),否则牌就发没了
*/
for (int i = 0; i < poker.size(); i++) { // poker: ?2 ?3 ?4 ?5 ?6 ?7
//获取每一张牌
String p = poker.get(i);
//轮流发
if(i>=51){
//给底牌发
diPai.add(p);
}else if(i%3==0){
//给玩家1发
player01.add(p);
}else if(i%3==1){
//给玩家2发
player02.add(p);
}else if(i%3==2){
//给玩家3发
player03.add(p);
}
}
//4.看牌
System.out.println("刘德华:"+player01);
System.out.println("周润发:"+player02);
System.out.println("周星驰:"+player03);
System.out.println("底牌:"+diPai);
}
}
六、补充扩展
1.可变参数
/*
可变参数定义格式:
数据类型...变量名
注意事项:
可变参数后面,不能再有其他参数了
可变参数前面,可以有其他参数的
*/
public class Test01 {
public static void main(String[] args) {
int sum = getSum("a",10,20,30,40,50);
System.out.println(sum);
}
//通过可变参数来作为方法的参数
public static int getSum(String s,int...num) {
int sum = 0;
for (int i = 0; i < num.length; i++) {
sum += num[i];
}
return sum;
}
}
2.适配器设计模式
-
假设有一个接口,接口中有多个抽象方法。但是实现类中我只需要用到其中的某个方法。但是如果一旦实现了接口,就必须重写所有的抽象方法!其余用不到的方法,也必须作为空实现放在本类中。此做法不合适。
-
解决方式:可以定义一个抽象类,实现接口。将用到的方法直接继承,其余用不到的方法作为空实现。定义子类,继承该抽象类。只需要重写用到的那一个抽象方法即可!
-
示例代码
-
接口
public interface MyInter { public abstract void eat(); public abstract void sleep(); public abstract void study(); public abstract void call(); public abstract void jump(); public abstract void run(); public abstract void lookHome(); } -
抽象类
public abstract class MyClassAbs implements MyInter{ @Override public void sleep() { } @Override public void study() { } @Override public void call() { } @Override public void jump() { } @Override public void run() { } @Override public void lookHome() { } } -
子类
public class MyClass extends MyClassAbs { @Override public void eat() { System.out.println("吃饭"); } } -
测试类
public class Test02 { public static void main(String[] args) { MyClass my = new MyClass(); my.eat(); } }
-
练习题
- 练习Collection接口常用的方法
- 练习迭代器遍历集合
- 练习增强for循环遍历集合和数组
- 练习定义泛型类、泛型方法、泛型接口的使用
- 练习泛型通配符的使用
面试题
- 请聊聊单列集合体系结构
- 集合和数组的区别是什么?
- 什么是泛型?
- 泛型有什么好处?
- 泛型向上限定指的是什么意思?
- 泛型向下限定指的是什么意思?
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




