java入门(Collection、泛型)

    技术2026-04-19  5

    Collection、泛型

    Collection

    概述

    集合就是容器,容器有数组,集合。

    集合和数组既然都是容器,它们有什么区别呢?

    数组的长度是固定的。集合的长度是可变的。

    数组中存储的是同一类型的元素,可以存储任意类型数据。集合存储的都是引用数据类型。如果想存储基本类型数据需要存储对应的包装类型。

    集合框架介绍

    集合Collection中常用的功能
    public boolean add(E e): 把给定的对象添加到当前集合中 。public void clear() :清空集合中所有的元素。public boolean remove(E e): 把给定的对象在当前集合中删除。public boolean contains(Object obj): 判断当前集合中是否包含给定的对象。public boolean isEmpty(): 判断当前集合是否为空。public int size(): 返回集合中元素的个数。public Object[] toArray(): 把集合中的元素,存储到数组中 /* Collection是接口,如果要创建对象需要借助其子类 */ public class Demo01 { public static void main(String[] args) { //借助Collection子类创建对象 Collection<String> coll = new ArrayList<>(); // 多态 //- public boolean add(E e): 把给定的对象添加到当前集合中 。 coll.add("迪丽热巴"); coll.add("古力娜扎"); coll.add("玛尔扎哈"); coll.add("德玛西亚"); System.out.println("coll = " + coll);//[迪丽热巴, 古力娜扎, 玛尔扎哈, 德玛西亚] //- public void clear() :清空集合中所有的元素。 //coll.clear(); //System.out.println("coll = " + coll); //[] //- public boolean remove(E e): 把给定的对象在当前集合中删除。 boolean remove = coll.remove("德玛西亚"); System.out.println("remove = " + remove); System.out.println("coll = " + coll);//[迪丽热巴, 古力娜扎, 玛尔扎哈] //- public boolean contains(Object obj): 判断当前集合中是否包含给定的对象。 boolean contains = coll.contains("德玛西亚"); System.out.println("contains = " + contains);//false boolean contains1 = coll.contains("古力娜扎"); System.out.println("contains1 = " + contains1);//true System.out.println("coll = " + coll); //- public boolean isEmpty(): 判断当前集合是否为空。 boolean empty = coll.isEmpty(); System.out.println("empty = " + empty);//false //- public int size(): 返回集合中元素的个数。 int size = coll.size(); System.out.println("size = " + size);//3 //- public Object[] toArray(): 把集合中的元素,存储到数组中 Object[] objects = coll.toArray(); System.out.println("objects = " + Arrays.toString(objects)); } }

    迭代器Iterator的使用

    1. 认识Iterator接口

    Iterator专门用来遍历集合

    含有方法:

    2. 如何获取集合对应的Iterator迭代器?

    Colleciton接口继承了一个接口Iterable,含有方法: 可以用以上方法获取一个集合的迭代器。

    因为Iterable是Colleciton的父接口,所有Collcetion的子类型都含有Iterable的方法:iterator的方法用来获取对应的迭代器。

    3. 迭代器的使用

    使用步骤:

    可以调用集合的方法iterator方法,获取迭代器通过迭代器对象的方法:hasNext方法判断是否有下一个元素。如果有下一个元素通过next方法获取元素。重复2,3步骤,直到hasNext方法执行返回false,遍历结束。

    以上步骤优化:

    可以调用集合的方法iterator方法,获取迭代器:ter

    借助while循环获取

    while(iter.hasNext()){ E e = iter.next(); }

    【代码实践】

    public class Demo01 { public static void main(String[] args) { //借助Collection子类创建对象 Collection<String> coll = new ArrayList<>(); // 多态 coll.add("迪丽热巴"); coll.add("古力娜扎"); coll.add("玛尔扎哈"); coll.add("德玛西亚"); //使用迭代器进行遍历 //1. 可以调用集合的方法iterator方法,获取迭代器 Iterator<String> iter = coll.iterator(); //2. 通过迭代器对象的方法:hasNext方法判断是否有下一个元素。 boolean result = iter.hasNext(); //3. 如果有下一个元素通过next方法获取元素。 if (result) { String next = iter.next(); System.out.println("next = " + next); } //4. 重复2,3步骤,直到hasNext方法执行返回false,遍历结束。 result = iter.hasNext(); if (result) { String next = iter.next(); System.out.println("next = " + next); } //以上写法太low了,不适用 //使用while循环进行优化 //获取迭代器 Iterator<String> iter2 = coll.iterator(); while (iter2.hasNext()) {//如果有下一个元素,执行循环体进行获取下一个元素,否则结束 String element = iter2.next();//获取下一个元素 System.out.println("element = " + element); } } }
    迭代器使用时的注意事项

    在使用迭代器进行遍历集合时,注意: 1)如果迭代器判断没有了元素,不能继续使用next方法获取元素,还继续取:oSuchElementException 2)当迭代器使用的过程中,不能直接使用集合对象进行增删数据,ConcurrentModificationException 如果一定要删除,可以使用迭代器自身的方法:remove

    public class Demo02 { public static void main(String[] args) { Collection<String> coll = new ArrayList<>(); coll.add("AAA1"); coll.add("AAA2"); coll.add("AAA3"); coll.add("AAA4"); coll.add("AAA5"); coll.add("AAA6"); Iterator<String> iter = coll.iterator(); while (iter.hasNext()) { String s = iter.next(); System.out.println("s = " + s); if ("AAA3".equals(s)) { //迭代器执行过程中,不能直接使用集合对象进行增删数据 //coll.remove("AAA3"); //如果要删除,可以使用迭代器的remove方法 iter.remove(); } } System.out.println("coll = " + coll); } }

    迭代器的使用操作原理介绍

    我们可以借助while循环完成以上循环获取元素的操作,当最后一个元素获取完成,不能继续获取。

    增强for循环的使用

    增强for循环专门用来遍历数组和集合的循环

    格式:

    for(变量类型 变量 : 数组/集合){ //操作变量,变量就是每次循环取出的元素 } 注意: 变量类型应该就是集合或者数组所存储的数据类型。

    小技巧:数组名/集合名.for 快速构建增强for循环。 【代码实践】

    public class Demo01 { public static void main(String[] args) { //增强for循环,专门用来遍历数组和集合 //遍历数组 int[] arr = {100, 200, 300}; for (int i : arr) { System.out.println("i = " + i); } //遍历集合 Collection<String> coll = new ArrayList<>(); coll.add("AAA1"); coll.add("AAA2"); coll.add("AAA3"); for (String e : coll) { System.out.println("e = " + e); } } }

    泛型的概述

    泛型:泛指任意的引用数据类型【就是使用的一种未知类型,具体在使用的时候进行确定】

    泛型也可以不写,如果不写,那么泛型指定类型默认为Object。

    public class Demo01 { public static void main(String[] args) { Collection coll = new ArrayList(); //泛型不指定具体类型,泛型指代的就是Object类型,意味着集合可以存储任意的类型数据。 coll.add("Hello"); coll.add("World"); coll.add(3.14); coll.add(1000); //有弊端,不利于后期数据的处理 for (Object o : coll) { //获取字符串的长度 System.out.println(((String) o).length()); //报错 } } }

    使用泛型好处:

    可以避免在后期使用数据时,不必要的类型转化让潜在的类型转化异常,提前到编译失败,强制程序员使用指定的数据 Collection<String> coll2 = new ArrayList<>(); coll2.add("Hello"); //coll2.add(1000); //可以将类型转化异常提前到编译异常,避免运行的时候报错

    泛型可以理解为类型的变量,使用时具体指定。有利于程序的开发。

    自定义泛型类及使用

    泛型类的定义和使用

    1)定义格式:类名后面加上 <泛型变量>

    public class 类名<A,B,C,...>{ //把A,B,C当作是某一种具体类型使用,成员变量的类型,方法参数的类型,方法返回值类型 }

    【例如】

    public class MyArrayList<D>{ private D d; public void setD(D d){ this.d=d; } }

    2)怎么使用,什么时候类的泛型可以确定为具体的类型。

    具体创建对象的时候,具体指定 public class Demo01 { public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); list.add("Hello"); // E = String MyArrayList<String> myList = new MyArrayList<>(); myList.setD("Hello"); // D = String } }

    在类中定义的泛型,在整个类都能使用

    自定义泛型的方法及使用

    怎么在方法中定义泛型【格式】

    在方法修饰符中添加一个泛型,这个泛型只能在本方法中使用

    修饰符<泛型变量> 返回值类型 方法名(参数列表){ }

    怎么使用,什么时候确定泛型的具体类型

    在具体调用该方法时,传入的数据是什么类型,那么该泛型就是什么类型

    自定义含有泛型的接口及使用

    如何定义【格式】?

    public interface 接口名<泛型变量>{} 例如: public interface Map<K,V>{}

    【代码实践】

    public interface MyCollection<W> { void add(W w); }

    什么时候能指定接口中泛型的具体类型?

    1:接口的泛型可以在子类实现的时候,具体指定

    public class MyCollectionImp implements MyCollection<String> { //W =String @Override public void add(String o) { } }

    2:如果子类无法确定泛型,可以在子类中类名后面定义一个泛型,在接口后面使用该泛型用,可以在创建这个子类对象的时候确定

    public class MyCollImp<W> implements MyCollection<W> { @Override public void add(W w) { } } //具体子类创建对象的时候进行指定泛型【泛型类的使用】 public class Demo01 { public static void main(String[] args) { MyCollImp<String> coll = new MyCollImp<>(); // W = String coll.add("Hello"); } }

    泛型通配符的基本使用

    泛型通配符:

    泛型通配符作用:如果想让我们得参数可以接收任意类型得泛型,就可以借助泛型通配符实现。

    注意:泛型通配符定义的集合,不支持增删操作,只支持读取操作

    /* 泛型通配符:? 作用:可以代表任意类型的泛型 注意:泛型通配符定义的集合,只能获取元素,不能增删数据 */ public class Demo01 { public static void main(String[] args) { ArrayList<String> list1 = new ArrayList<>(); ArrayList<Integer> list2 = new ArrayList<>(); ArrayList<Number> list3 = new ArrayList<>(); ArrayList<Object> list4 = new ArrayList<>(); //具体泛型只能接收具体类型 //printArrayList(list1); //x //printArrayList(list2); //x 泛型没有多态 //printArrayList(list3); //printArrayList(list4);//x //泛型通配符,可以接收任意得泛型 printArrayList2(list1); printArrayList2(list2); printArrayList2(list3); printArrayList2(list4); } public static void printArrayList2(ArrayList<?> list) { //list.add(1000); for (Object o : list) { System.out.println("o = " + o); } } public static void printArrayList(ArrayList<Number> list) { list.add(1000); for (Number n : list) { } } }

    受限泛型的使用

    【代码实践】

    public class Demo01 { public static void main(String[] args) { ArrayList<String> list1 = new ArrayList<>(); ArrayList<Integer> list2 = new ArrayList<>(); ArrayList<Number> list3 = new ArrayList<>(); ArrayList<Object> list4 = new ArrayList<>(); //泛型上限:只能接收 Number及其子类类型 //print1(list1); //X 和Number没关系 print1(list2);// Integer 是Number的子类 print1(list3);// Number 自己也可以 //print1(list4);// Object 是Number父类 //泛型下限:只能接收 Number及其父类类型 //print2(list1); // X 和Number没关系 //print2(list2); // X Integer 是Number的子类 print2(list3); // Number 自己也可以 print2(list4); // Object 是Number父类 } //泛型上限:只能接收 Number及其子类类型 public static void print1(ArrayList<? extends Number> list) { } //泛型下限:只能接收 Number及其父类类型 public static void print2(ArrayList<? super Number> list) { } }

    斗地主案例

    /* 1.准备牌 2.洗牌 3.发牌 4.看牌 */ public class Demo01 { public static void main(String[] args) { //1.准备牌 ArrayList<String> pokers = new ArrayList<>();//集合用来存储牌 String[] colors = {"♥", "♠", "♣", "♦"}; String[] points = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"}; //花牌组装 for (String color : colors) { for (String point : points) { //System.out.println(color+point); pokers.add(color + point); } } //大王/小王 pokers.add("大🃏"); pokers.add("小🃏"); //System.out.println(pokers.size()+"::"+pokers); //2.洗牌 Collections.shuffle(pokers); //System.out.println(pokers.size() + "::" + pokers); //3.发牌 ArrayList<String> player1 = new ArrayList<>(); ArrayList<String> player2 = new ArrayList<>(); ArrayList<String> player3 = new ArrayList<>(); ArrayList<String> dipai = new ArrayList<>(); for (int i = 0; i < pokers.size(); i++) { String poke = pokers.get(i); if (i > 50) { dipai.add(poke); } else if (i % 3 == 0) { player1.add(poke); } else if (i % 3 == 1) { player2.add(poke); } else if (i % 3 == 2) { player3.add(poke); } } //4.看牌 System.out.println("星仔:" + player1); System.out.println("小高:" + player2); System.out.println("华仔:" + player3); System.out.println("底牌:" + dipai); } }

    发牌逻辑

    Processed: 0.016, SQL: 9