Java 基础之 Collection 集合

1. 集合概述

java.util.Collection 集合也是一种容器,与数组的区别:

  • 数组:长度固定,数据类型一致
  • 集合:存储的为对象,对象类型可不一致,长度也不固定,比较常用

Collection 按存储结构分类

  • 单列集合类 java.util.Collection:它有两个重要的子接口:java.util.List、java.util.Set
    • List:元素有序、元素可重复
    • Set:无序,不可重复
  • 双列集合java.util.Map

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-49KOKkhL-1673620095039)(https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg-blog.csdnimg.cn%2F20190926201633911.png%3Fx-oss-process%3Dimage%2Fwatermark%2Ctype_ZmFuZ3poZW5naGVpdGk%2Cshadow_10%2Ctext_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjU0MTI1NA%3D%3D%2Csize_16%2Ccolor_FFFFFF%2Ct_70&refer=http%3A%2F%2Fimg-blog.csdnimg.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1652778572&t=175a3828bfd97568fe0773ece7688767)]

1.1 集合常用功能

下面是一些单列集合通用的方法:

  • public boolean add(E e): 把给定的对象添加到当前集合中
  • public void clear() :清空集合中所有的元素
  • public boolean remove(E e):把给定的对象在当前集合中删除
  • public boolean contains(E e): 判断当前集合中是否包含给定的对象
  • public boolean isEmpty():判断当前集合是否为空
  • public int size():返回集合中元素的个数
  • public Object[] toArray(): 把集合中的元素,存储到数组中
import java.util.ArrayList;
import java.util.Collection;

public class CollectionSingle {
    public static void main(String[] args) {
        Collection<String> coll = new ArrayList<>();
        coll.add("张三");
        coll.add("李四");

        System.out.println(coll.contains("张三"));
        System.out.println(coll.size());
        System.out.println(coll.isEmpty());
        coll.remove("李四");

        // 转换为数组
        Object[] object = coll.toArray();
        for (int i = 0; i < object.length; i++) {
            System.out.println(object[i]);
        }

        coll.clear();
    }
}

2. Iterator 迭代器

java.util.Iterator 迭代器用于遍历集合元素,它有两个方法:

  • next():获取下一个元素
  • hasNext():判断是否还有下一个元素,使用时先判断是否有下一个元素,以防出现 java.util.NoSuchElementException
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class IteratorDemo {
    public static void main(String[] args) {
        Collection<String> coll = new ArrayList<String>();
        coll.add("rose");
        coll.add("lila");
        coll.add("john");

        Iterator<String> iterator = coll.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

2.1 增强型 for 循环

增强for循环(也称for each循环),专门用来遍历数组和集合的。它的内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作

格式:

for(元素的数据类型  变量 : Collection集合or数组){ 
  	//写操作代码
}

示例:

public class IteratorDemo {
    public static void main(String[] args) {
        Collection<String> coll = new ArrayList<String>();
        coll.add("rose");
        coll.add("lila");
        coll.add("john");

        for (String s: coll) {
            System.out.println(s);
        }
    }
}

3. 泛型

3.1 泛型的好处

集合可以存储任意对象,只要将对象存储到集合后,就会自动提升为 Object 类型。当取出对象并做相应操作,就必须类型转换:

public class GenericDemo {
    public static void main(String[] args) {
        Collection coll = new ArrayList();
        coll.add("rose");
        coll.add("lila");
        coll.add(5);

        Iterator iterator = coll.iterator();
        while (iterator.hasNext()) {
            // 强制为 String 类型,引发 java.lang.ClassCastException 
            String str = (String) iterator.next();
            System.out.println(str);
        }
    }
}

通常Collection只存储同一类型对象。例如都是存储字符串对象。因此在JDK5之后,新增了泛型(Generic)语法,让你在设计API时可以指定类或方法支持泛型,这样我们使用API的时候也变得更为简洁,并得到了编译时期的语法检查

泛型的好处

  • 将运行时期的 ClassCastException 转移到编译时期变成编译失败
  • 避免类型强制麻烦,提升性能(遍历时,由于返回类型为 Object,如果要使用子类特有方法或属性,需要向下转型)
  • 对集合中的 ArrayList 的数据类型进行约束
public class GenericDemo {
    public static void main(String[] args) {
        Collection<String> coll = new ArrayList<String>();
        coll.add("rose");
        coll.add("lila");
//        coll.add(5);  //当集合明确类型后,存放类型不一致就会编译报错

//        集合已经明确具体存放的元素类型,那么在使用迭代器的时候,迭代器也同样会知道具体遍历元素类型
        Iterator<String> iterator = coll.iterator();
        while (iterator.hasNext()) {
            String str = iterator.next();
            System.out.println(str);
        }
    }
}

3.2 泛型的定义及使用

泛型,用来灵活地将数据类型应用到不同的类、方法、接口当中。将数据类型作为参数进行传递

3.2.1 定义和使用含有泛型的类

格式:

修饰符 class 类名<代表泛型的变量> {  }

示例:

// 自定义泛型类
public class GenericClassDemo {
    public static void main(String[] args) {
        // 创建一个泛型为 String 类型的类
        MyGenericMVP<String> my = new MyGenericMVP<String>();
        my.setMVP("rose");
        System.out.println(my.getMVP());

        // 定义一个泛型为 Int 类型的类
        MyGenericMVP<Integer> my1 = new MyGenericMVP<Integer>();
        my1.setMVP(1);
        System.out.println(my1.getMVP());
    }
}

// MVP 不知道的数据类型
class MyGenericMVP<MVP> {
    private MVP mvp;

    public void setMVP(MVP mvp) {
        this.mvp = mvp;
    }

    public MVP getMVP() {
        return mvp;
    }
}

3.2.2 含有泛型的方法

格式:

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

示例:

使用格式:调用方法时,确定泛型的类型

public class MyGenericMethod {
    public static void main(String[] args) {
        GenericMethodDemo mm = new GenericMethodDemo();
        mm.show("aaa");
        mm.show(123);
        System.out.println(mm.show2(1234));
    }
}

class GenericMethodDemo {
    public <MVP> void show(MVP mvp) {
        System.out.println(mvp.getClass());
    }

    public <MVP> MVP show2(MVP mvp) {
        return mvp;
    }
}

3.2.3 含有泛型的接口

定义格式:

修饰符 interface接口名<代表泛型的变量> {  }

示例:

interface GenericInterface<E> {
    public abstract void add(E e);

    public abstract E getE();
}

1、 定义类时确定泛型类型

// 此时泛型 E 的值就是 String 类型
class MyImp1 implements GenericInterface<String> {
    @Override
    public void add(String e) {

    }

    @Override
    public String getE() {
        return null;
    }
}

2、使用时确定泛型类型

class MyImp2<E> implements GenericInterface<E> {
    @Override
    public void add(E e) {
    }

    @Override
    public E getE() {
        return null;
    }
}

使用:

public class MyGenericInterface {
    public static void main(String[] args) {
        MyImp2<String> my = new MyImp2<String>();
        my.add("aa");
    }
}

3.3 泛型通配符

当使用泛型类或者接口时,传递的数据中,泛型类型不确定,可以通过通配符<?>表示。但是一旦使用泛型的通配符后,只能使用Object类中的共性方法,集合中元素自身方法无法使用

public class MyGenericInterface {
    public static void main(String[] args) {
        // 泛型通配符
        Collection<String> coll1 = new ArrayList<String>();
        getElement(coll1);
        
        Collection<Integer> coll2 = new ArrayList<Integer>();
        getElement(coll2);
    }

    // 泛型通配符,可接收任意类型
    public static void getElement(Collection<?> coll) {}
}

注意:泛型不存在继承关系 Collection<Object> list = new ArrayList<String>();这种是错误的

3.3.1 通配符高级使用----受限泛型

之前设置泛型的时候,实际上是可以任意设置的,只要是类就可以设置。但是在JAVA的泛型中可以指定一个泛型的上限下限

泛型的上限

  • 格式类型名称 <? extends 类 > 对象名称
  • 意义只能接收该类型及其子类

泛型的下限

  • 格式类型名称 <? super 类 > 对象名称
  • 意义只能接收该类型及其父类型

比如:现已知Object类,String 类,Number类,Integer类,其中NumberInteger的父类:

public static void main(String[] args) {
    Collection<Integer> list1 = new ArrayList<Integer>();
    Collection<String> list2 = new ArrayList<String>();
    Collection<Number> list3 = new ArrayList<Number>();
    Collection<Object> list4 = new ArrayList<Object>();
    
    getElement(list1);
    getElement(list2);//报错
    getElement(list3);
    getElement(list4);//报错
  
    getElement2(list1);//报错
    getElement2(list2);//报错
    getElement2(list3);
    getElement2(list4);
  
}
// 泛型的上限:此时的泛型?,必须是Number类型或者Number类型的子类
public static void getElement1(Collection<? extends Number> coll){}

// 泛型的下限:此时的泛型?,必须是Number类型或者Number类型的父类
public static void getElement2(Collection<? super Number> coll){}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风老魔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值