【Java】Collection集合和泛型

学习目标:会存取,掌握特性
学习方式:学习顶层接口/抽象类的共性方法,使用底层的子类创建对象使用

1 集合框架

集合类的继承体系:
Collection接口:
·············1) List接口:有序、允许重复、有索引
··························1.1) ArrayList集合【重点】
··························1.2) Vector集合【了解】
··························1.3) LinkedList集合【熟悉】
·············2) Set接口:不重复、无索引
··························2.1) TreeSet集合:无序(存取顺序可能不一致)【了解】
··························2.2) HashSet集合:无序【重点】
·······································2.2.1) LinkedHashSet集合:无序【熟悉】

集合 特点
List 有索引,可以存储重复元素,可以保证存取顺序
ArrayList 底层是数组实现的,查询快,增删慢
LinkedList 底层是链表实现的,查询慢,增删快
Set 无索引,不可以存储重复元素,存取无序
HashSet 底层是哈希表+红黑树实现,无索引,不可以存重复元素,存取无序
LinkedHashSet 底层是哈希表+链表实现,无索引,不可以存重复元素,可以保证存取顺序
TreeSet 底层是二叉树实现,一般用于排序

2 Collection集合常用功能

Collection是单列结合最顶层的接口,定义了单列集合共性方法,任意单列集合都可以使用
java.util.Collection:1. add(e); 2. remove(e); 3. inEmpty(); 4. clear(); 5. contains(e); 6. toArray(); 7. size()

public static void main(String[] args) {
    
    
        Collection<String> coll = new ArrayList<>();
        //add添加元素
        coll.add("a");
        coll.add("b");
        coll.add("c");
        System.out.println(coll);//[a,b,c]

        //remove删除元素
        boolean result = coll.remove("a");
        System.out.println(result);//删除结果:true
        System.out.println(coll);//[b,c]

        //clear清空集合
        coll.clear();
        System.out.println(coll);

        //contains是否包含
        coll.add("b");
        boolean result2 = coll.contains("a");
        System.out.println(result2);//flase
        boolean result3 = coll.contains("b");
        System.out.println(result3);//true

        //isEmpty判断集合是否为空
        System.out.println(coll.isEmpty());//false

        //size获取集合长度
        System.out.println(coll.size());//1

        //toArray集合--->数组 遍历集合元素
        Object[] arr = coll.toArray();
        for (int i = 0; i < arr.length; i++) {
    
    
            System.out.println(arr[i]);//打印Object对象 因为重写了toString 所以显示的是值而不是地址
        }
}

3 Iterator迭代器

常用方法:1. hasNext()、2. next()
Iterator迭代器是一个接口,无法直接使用,需要使用Iterator接口的实现类对象
Collection中有一个iterator()方法,返回的是迭代器的实现类对象,list和set 通用,无需索引。
【重点】使用方式

  1. 使用iterator()方法获取实现类对象,使用Iterator接口接收(多态)
  2. 使用hasNext判断是否还有下一个
  3. 使用next取出下一个元素

实现原理:iterator()获取迭代器的实现类对象,会把指针(索引)指向集合-1索引处。hasNext()判断是否有下一个。next取出一个元素后,会把指针向后移动一位。

实现示例

public static void main(String[] args) {
    
    
        Collection<String> coll = new ArrayList<>();
        coll.add("a");
        coll.add("b");
        coll.add("c");
        coll.add("d");
        coll.add("e");
        //迭代器有泛型 跟着集合走
        //多态    接口          实现类对象
        Iterator<String> it = coll.iterator();
        while(it.hasNext()){
    
    
            System.out.println(it.next());
        }
    }    public static void main(String[] args) {
    
    
        Collection<String> coll = new ArrayList<>();
        coll.add("a");
        coll.add("b");
        coll.add("c");
        //迭代器有泛型 跟着集合走
        //多态    接口          实现类对象
        Iterator<String> it = coll.iterator();
        //常用while循环
        while(it.hasNext()){
    
    
            String e = it.next();
            System.out.println(e);
        }
        
        //一个迭代器只能取一次 再取要创建新的迭代器 否则会报NoSuchElement异常
        for( Iterator<String> it2 = coll.iterator();it2.hasNext();){
    
    
            String e = it2.next();
            System.out.println(e);
        }

		//foreach语句 增强for循环JDK1.5开始出现 
        //专门用来遍历数组和结合 
        //底层使用的也是迭代器遍历过程中只能遍历不能增删
        for(Object o : coll){
    
    
            System.out.println(o);
        }
    }

4 泛型的概念

概念
泛型是一种未知的数据类型,当不知道使用什么数据类型的时候可以使用泛型
泛型也可以看成是一个变量用来接收数据类型
ArrayList<E>,E表示未知类型,在创建集合对象时,确定泛型的数据类型
不使用泛型的好处:使用泛型,默认类型时Object类型,可以存储任意类型的数据
不适用泛型的弊端:不安全,会引发异常

public static void main(String[] args) {
    
    
        Collection ArrayList = new ArrayList();
        //以Object类型存入任意类型的数据
        ArrayList.add("a");
        ArrayList.add(1);
        Iterator it = ArrayList.iterator();
        while(it.hasNext()){
    
    
            //取出也是Object类型
            System.out.println(it.next());

            //引发异常举例:
            //想要使用String类特有的方法不能使用
            //多态:Object obj = "a"不能使用子类特有的方法
            //除非向下转型(String)"a"
            Object o = it.next();
            //当o=1时,java.lang.ClassCastException:
            String s = (String) o;
            System.out.println(s.length());
        }
    }

使用泛型的好处:避免了类型转换的麻烦,把运行期异常,提升到了编译期(IDE会报错)
使用泛型的弊端:只能存储泛型定义的类型

5 泛型的定义和使用

5.1 定义和使用泛型类

泛型类

package Collection;

public class GenericClass<E> {
    
    
    private E name;

    public E getName() {
    
    
        return name;
    }

    public void setName(E name) {
    
    
        this.name = name;
    }
}

泛型测试类

package Collection;

public class GenericClassTest {
    
    
    public static void main(String[] args) {
    
    
        GenericClass<String> gcs = new GenericClass<>();
        gcs.setName("张三");
        System.out.println(gcs.getName());

        GenericClass<Integer> gci = new GenericClass<>();
        gci.setName(1);
        System.out.println(gci.getName());
    }
}

5.2 定义和使用泛型的方法

泛型定义在方法修饰符和返回值类型之间
在调用方法时确定泛型的数据类型,传递什么类型的参数,泛型就是什么类型

修饰符 <泛型> 返回值类型 方法名(参数表(使用泛型))

定义类和方法

public class GenericMethod {
    
    
    //成员方法
    public <M> void method(M m){
    
    
        System.out.println(m);
    }
    //静态方法
    public static <M> void methodStatic(M m){
    
    
        System.out.println(m);
    }
}

测试类调用

public class GenericMethodTest {
    
    
    public static void main(String[] args) {
    
    
        //创建对象
        GenericMethod gm = new GenericMethod();
        gm.method(10);
        gm.method("abc");
        gm.method(9.99);

        GenericMethod.methodStatic(5);
        GenericMethod.methodStatic("zxc");
    }
}

5.3 定义和使用泛型接口

方法1:使用实现类,指定接口的泛型

  1. 定义接口:
public interface GenericInterface<I> {
    
    
    public abstract void method(I i);
}
  1. 定义实现类:【指定泛型类型】
public class GenericInterfaceImpl implements GenericInterface<String> {
    
    
    @Override
    public void method(String s) {
    
    
        System.out.println(s);
    }
}
  1. 定义测试类:
public class GenericInterfaceTest {
    
    
    public static void main(String[] args) {
    
    
        GenericInterfaceImpl gi = new GenericInterfaceImpl();
        gi.method("abc");

    }   
}

方法2:接口使用什么泛型实现类就用什么泛型

  1. 定义接口
public interface GenericInterface<I> {
    
    
    public abstract void method(I i);
}
  1. 定义实现类【不指定泛型类型】
public class GenericInplementImpl2<I> implements GenericInterface<I>{
    
    
    @Override
    public void method(I i) {
    
    
        System.out.println(i);
    }
}
  1. 定义测试类【创建对象时,指定泛型类型】
public class GenericInterfaceTest {
    
    
    public static void main(String[] args) {
    
    
        GenericInplementImpl2<Integer> gi2 = new GenericInplementImpl2<>();
        gi2.method(123);
    }
}

5.3 泛型通配符

不知道使用什么类型来接收数据的时候,可以使用<?>表示未知通配符
此时只能接收数据,不能往集合中存储数据
定义的时候不能用 只有参数传递的时候可以用

import java.util.ArrayList;
import java.util.Iterator;

public class Generic {
    
    
    //定义一个方法,可以遍历有所ArrayList集合
    //不知道集合的数据类型,可以使用泛型来接受数据类型

    //注意!!泛型没有继承概念,所以不能用Object
//    错误写法:
//    public static void printArray(ArrayList<Object> list){
    
    
//
//    }
//    正确写法:
    public static void printArray(ArrayList<?> list){
    
    
        Iterator<?> it = list.iterator();
        while(it.hasNext()){
    
    
            //it.next()取出的时Object类型
            Object obj = it.next();
            System.out.print(obj + " ");
        }
        System.out.println();
    }
    public static void main(String[] args) {
    
    
        ArrayList<Integer> list1 = new ArrayList<>();
        list1.add(1);
        list1.add(2);

        ArrayList<String> list2 = new ArrayList<>();
        list2.add("a");
        list2.add("b");
		//?= Integer
        printArray(list1);
        //? = String
        printArray(list2);
    }
}

泛型通配符的高级使用——受限泛型【看源码的时候可能会用】
泛型的上限限定:? extends E 表示使用的泛型只能是E的子类/本身
泛型的下限限定:? super E 表示使用的泛型只能时E的父类/本身

import java.util.ArrayList;
import java.util.Collection;

public class GenericUpDown {
    
    
    //上限限定,?只能是子类/本身
    public static void getElementUp(Collection<? extends Number> coll){
    
    }
    
    //下限限定,?只能是父类/本身
    public static void getElementDown(Collection<? super Number> coll){
    
    }
    
    public static void main(String[] args) {
    
    
        // 继承关系
        // int extends num extends obj
        // str extends obj
        Collection<Integer> intList = new ArrayList<>();
        Collection<String> strList = new ArrayList<>();
        Collection<Number> numList = new ArrayList<>();
        Collection<Object> objList = new ArrayList<>();
        
        getElementUp(intList);
//      getElementDown(intList); // 报错 int是num的子类
       
//      getElementUp(strList); // 报错 str和num没关系
//      getElementDown(strList); // 报错 str和num没关系
        getElementUp(numList);
        getElementDown(numList);
//      getElementUp(objList); // 报错 obj是num的父类
        getElementDown(objList);
    }
}

案例:斗地主-1

package DouDiZhu;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;

public class DouDiZhu {
    
    

    public static void main(String[] args) {
    
    
        //1. 准备牌面
        ArrayList<String> all = new ArrayList<>();
        all.add("BK");
        all.add("SK");
        String[] colors = {
    
    "♥","♠","♦","♣"};
        String[] nums = {
    
    "A","K","Q","J","10","9","8","7","6","5","4","3","2"};
        for(String num: nums){
    
    
            for(String color: colors){
    
    
                all.add(color+num);
            }
        }
        //2. 洗牌
        Collections.shuffle(all);//打乱顺序
        ArrayList<String> left = new ArrayList<>();
        ArrayList<String> p1 = new ArrayList<>();
        ArrayList<String> p2 = new ArrayList<>();
        ArrayList<String> p3 = new ArrayList<>();
        for (int i = 0; i < all.size(); i++) {
    
    
            String p = all.get(i);
            if(i>=51){
    
    
                left.add(p);
            }else{
    
    
                if(i%3 == 0){
    
    
                    p1.add(p);
                }else if(i%3 == 1){
    
    
                    p2.add(p);
                }else{
    
    
                    p3.add(p);
                }
            }
        }
        //3. 看牌
        System.out.println(p1);
        System.out.println(p2);
        System.out.println(p3);
        System.out.println(left);
    }
}

猜你喜欢

转载自blog.csdn.net/xd963625627/article/details/105251026