Java-Collection、泛型

Collection集合

集合:集合是Java中提供的一种容器,可以用来存储多个数据

集合和数组都是容器,但是两者有较大的区别:

  1. 数组的长度是固定的,而集合的长度是可以变的
  2. 数组中存储的是同一类型的数据,可以存储基本数据类型;集合存储的都是对象,而对象的类型可以不一致,当对象过多的时候就是用集合来进行存储
集合框架

集合按照存储结构可以分为两大类,单列集合java.util.Collection双列集合java.util.Map

  • Collection:单列集合类的根接口,用于存储一系列符合某种规律的元素,有List和Set两个重要的子接口
    1. List的特点是元素有序、元素可重复
      • 主要实现类:java.util.ArrayListjava.util.LinkedList
    2. Set的特点是元素无须、且不可重复
      • 主要实现类:java.util.HashSetjava.util.TreeSet
Collcetion集合当中的常用方法:
  • 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(): 把集合中的元素,存储到数组中。
Collection<String> coll = new ArrayList<String>();
coll.add("你好");
//利用对象名.方法名来调用,比较简单,不一一举例
Iterator迭代器

java.util.IteratorIterator接口也是Java集合中的一员,但它与CollectionMap接口有所不同,Collection接口与Map接口主要用于存储元素,而Iterator主要用于迭代访问(即遍历Collection中的元素,因此Iterator对象也被称为迭代器。

  • public Iterator iterator(): 获取集合对应的迭代器,用来遍历集合中的元素的。

迭代:在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来。然后继续判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。

常用方法

  • public E next():返回迭代的下一个元素。
  • public boolean hasNext():如果仍有元素可以迭代,则返回 true。

Iterator迭代器是一个接口,无法直接使用,需要使用Iterator接口的实现类对象来获取。Collection接口中有一个方法叫做Iterator(),这个方法返回的就是迭代器的实现类对象

迭代器的使用步骤:

  1. 使用集合中的Iterator()方法获取迭代器的实现类对象
  2. 用hasNext()进行判断是否有下一个元素
  3. 使用next()取出集合中的下一个元素
package Demo04;

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

public class DemoIterator {
    public static void main(String[] args) {
        Collection<String> coll = new ArrayList<String>();
        coll.add("科比");
        coll.add("库里");
        coll.add("詹姆斯");
        coll.add("杜兰特");
        coll.add("欧文");

        Iterator<String> it = coll.iterator();  //使用集合中的Iterator()方法获取迭代器的实现类对象
        while (it.hasNext()){   //用hasNext()进行判断是否有下一个元素
            System.out.println(it.next());  //使用next()取出集合中的下一个元素
        }
    }
}
增强for循环

高级for循环,专门用来遍历数组和集合,他的内部原理其实是一个迭代器(简化迭代器的写法),所以在便利的过程中,不能对集合中的元素进行增删改查

格式:

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

示例:

package Demo04;

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

public class DemoFor {
    public static void main(String[] args) {
        int[] arr = {1,2,3,4,5};
        for (int i:arr) {
            System.out.println(i);
        }

        Collection<String> coll = new ArrayList<String>();
        coll.add("aaa");
        coll.add("bbb");
        coll.add("ccc");
        coll.add("ddd");
        coll.add("eee");
        for (String s:coll) {
            System.out.println(s);
        }
    }
}

泛型

泛型的好处
  • 在创建集合对象的时候,不使用泛型:

​ 好处:集合不使用泛型,默认的类型就是Object类型,可以存储任意类型的数据

​ 坏处:不安全,会引发异常

package Demo04;

import java.sql.SQLOutput;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Objects;

public class DemoFanXing {
    public static void main(String[] args) {
        show01();
    }

    private static void show01() {
        ArrayList list = new ArrayList();
        list.add("abc");
        list.add(1);
        Iterator it = list.iterator();
        while(it.hasNext()){
            Object obj = it.next();
            System.out.println(obj);
            
            String s = (String)obj;
            System.out.println(s.length());

            /*
            abc
            3
            1
            Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
            抛出异常,Integer类型不能转换为String类型,所以不安全
            */
        }
    }
}

  • 在创建对象时,使用泛型:

​ 好处:避免了类型转换的麻烦,存什么类型,就取什么类型;把运行期异常(代码运行后会抛出异常)转换为编译期异常(写代码时就会报错)

​ 坏处:泛型是什么类型,就只能存什么样的数据,类型固定

package Demo04;

import java.sql.SQLOutput;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Objects;

public class DemoFanXing {
    public static void main(String[] args) {
        show02();
    }

    private static void show02() {
        ArrayList<String> list = new ArrayList<String>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        list.add("ddd");
        list.add("eee");
        //list.add(1);  在编写代码的时候就会有红色的下划线报错,不能存入整数
        Iterator<String> it = list.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
            System.out.println(it.next().length()); //可以直接用String类型的方法,就不用进行类型的转换,从而避免了类型转换时出现的错误
        }
    }
}
泛型的定义与使用
定义和使用含有泛型的类:

定义格式:修饰符 class 类名<代表泛型的变量> { }

注意:创建对象的时候,就确定泛型的数据类型

//不使用泛型的DemoGeneric类
package Demo04;

public class DemoGeneric {
    private String name;

    public String getName() {
        return name;
    }

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

//主函数
package Demo04;

public class DemoGenericTest {
    public static void main(String[] args) {
        DemoGeneric gc = new DemoGeneric();
        gc.setName("库里");   //DemoGeneric类中是private String name,所以只能set一个字符串类型的数据
        //gc.setName(1);这个就会出错,不能放入整数类型的数据
        System.out.println(gc.getName());   //返回也只能返回字符串类型的数据
    }
}

//使用泛型的DemoGeneric类
package Demo04;
/*
定义一个含有泛型的类
泛型是一个未知的数据类型,当我们不确定什么数据类型的时候,可以使用泛型
泛型可以接受任意的数据类型,可以使用Integer、String、Student等等
创建对象的时候,就确定泛型的数据类型
*/

public class DemoGeneric<E> {	//定义一个泛型的类
    private E name;

    public E getName() {
        return name;
    }

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

//主函数
package Demo04;

public class DemoGenericTest {
    public static void main(String[] args) {
        DemoGeneric<Integer> gc = new DemoGeneric();
        gc.setName(1);	
        //创建对象的时候,就确定泛型的数据类型,其中能够加入什么类型的数据,就是跟着< >中的类型来判断的
        DemoGeneric<String> gc1 = new DemoGeneric<>();
        gc1.setName("库里");
    }
}

定义和使用含有泛型的方法:

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

注意:调用方法的时候确定泛型的数据类型

//含有泛型的静态方法
package Demo04;

import java.lang.reflect.Type;

/*
定义含有泛型的方法:泛型定义方法在方法的修饰符和返回值之间
含有泛型的方法,在调用方法的时候确定泛型的数据类型
传递什么类型,就是什么类型
 */
public class DemoGenericMethod {
    public <M> void method01(M m){
        System.out.println(m);
    }

    //含有泛型的静态方法
    public static <E> void method02(E m){
        System.out.println(m);
    }
}

//主函数
package Demo04;

public class DemoGenericMethodTest {
    public static void main(String[] args) {
        DemoGenericMethod gm = new DemoGenericMethod();
        gm.method01(1);
        gm.method01("abc");
        gm.method01(3.1415926);
        gm.method01(true);  //传入什么类型就是什么类型的数据
        
        gm.method02("不建议");
        gm.method02(1);
    }
}


含有泛型的接口:

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

//定义接口
package Demo04;

public interface DemoGenericInterface<I> {
    public abstract void method(I i);
}

package Demo04;
/*
含有泛型的接口:
第一种使用方式:定义接口的实现类,实现接口,指定接口的泛型
*/
public class GenericInterfaceImpl01 implements DemoGenericInterface<String>{
    @Override
    public void method(String s) {
        System.out.println(s);
    }
}

//主函数
package Demo04;

public class GenericInterface {
    public static void main(String[] args) {
        GenericInterfaceImpl01 gi1 = new GenericInterfaceImpl01();
        gi1.method("abc");	//abc
    }
}

//定义接口
package Demo04;

public interface DemoGenericInterface<I> {
    public abstract void method(I i);
}

package Demo04;
/*
含有泛型的接口:
第二种使用方式:接口什么类型,实现类就用什么类型,类跟着接口走
*/
public class GenericInterfaceImpl02<E> implements DemoGenericInterface<E>{
    @Override
    public void method(E e) {
        System.out.println("02"+e);
    }
}


//主函数
package Demo04;

public class GenericInterface {
    public static void main(String[] args) {
        GenericInterfaceImpl01<String> gi2 = new GenericInterfaceImpl01<>();
        gi1.method("abc");	//02abc
    }
}

泛型通配符

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

package Demo04.Generic;

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

/*
泛型的通配符:
    ?代表任意的数据类型
使用方式:
    不能创建对象使用
    只能作为方法的参数使用
*/
public class DemoTong {
    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");
        
        print(list01);
        print(list02);
    }

    /*
        定义一个方法,能够遍历所有类型的ArrayList集合
        但是这个时候我们不知道ArrayList集合使用说明数据类型,就可以使用泛型通配符?
    */
    public static void print(ArrayList<?> list){    //可以接受任意的数据类型
        Iterator<?> it = list.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
    }
}

受限泛型:

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

泛型的上限

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

泛型的下限

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

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

package Demo04.Generic;

import java.util.ArrayList;

public class DemoTongXianZhi {
    public static void main(String[] args) {
        ArrayList<Integer> list1 = new ArrayList<Integer>();
        ArrayList<String> list2 = new ArrayList<String>();
        ArrayList<Number> list3 = new ArrayList<Number>();
        ArrayList<Object> list4 = new ArrayList<Object>();

        print1(list1);
        print1(list2);//报错
        print1(list3);
        print1(list4);//报错

        print2(list1);//报错
        print2(list2);//报错
        print2(list3);
        print2(list4);

    }
    // 泛型的上限:此时的泛型?,必须是Number类型或者Number类型的子类
    public static void print1(ArrayList<? extends Number> list){}
    // 泛型的下限:此时的泛型?,必须是Number类型或者Number类型的父类
    public static void print2(ArrayList<? super Number> list){}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值