暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

java-进阶-day02-随堂笔记

原创 手机用户9600 2023-07-10
188

课堂知识点

一、单列集合体系结构

1.什么是单列集合

? 单列集合一次只能存储一个元素

2.Collection接口

? 是单列集合最顶层的接口。提供了一些特别共性的方法。只要是单列集合实现类,都可以使用这些方法

3.单列集合体系图

? 01

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.迭代器实现原理

02

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(); } }

练习题

  1. 练习Collection接口常用的方法
  2. 练习迭代器遍历集合
  3. 练习增强for循环遍历集合和数组
  4. 练习定义泛型类、泛型方法、泛型接口的使用
  5. 练习泛型通配符的使用

面试题

  • 请聊聊单列集合体系结构
  • 集合和数组的区别是什么?
  • 什么是泛型?
  • 泛型有什么好处?
  • 泛型向上限定指的是什么意思?
  • 泛型向下限定指的是什么意思?
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论