Java集合与泛型

Java集合与泛型(黑马程序员)

1、Collection

1.1、集合知识回顾

集合类的特点:提供一种存储空间可变的存储模型,存储的数量容器会随时发生改变

1.2、集合类体系结构

在这里插入图片描述

1.3、Collection集合概述和使用

Collection集合概述

  • 是单例集合的顶层接口,它表示一组对象,这些对象也称为Collection的元素
  • JDK不提供此接口的任何直接实现,它提供更具体的子接口(如Set和List)实现

创建Collection集合的对象

  • 多态的方式
  • 具体的实现类ArraryList
import java.util.ArrayList;
import java.util.Collection;

public class CollectionDemo1 {
    public static void main(String[] args) {
        //创建collection集合的对象
        Collection<String> c = new ArrayList<String>();
        //添加元素,boolean add(E e)
        c.add("hello");
        c.add("my");
        c.add("dp");

        //输出集合对象
        System.out.println(c);//结果为[hello, my, dp]

    }
}

1.4、Collection 集合常用方法

在这里插入图片描述

/*
    Collection集合常用方法:
        boolean add(E e)添加元素
        boolean remove(Object o) 从集合中移除指定的元素
        void clear()    清空集合中的元素
        boolean contains(Object o)  判断集合中是否存在指定的元素
        boolean isEmpty()   判断集合是否为空
        int size()     集合的长度,也就是集合中元素的个数
 */

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

public class CollectionDemo2 {

    public static void main(String[] args) {
        //创建集合对象
        Collection<String> c = new ArrayList<String>();
        //boolean add(E e)添加元素
        c.add("hello");
        c.add("my");
        c.add("dp");
        //输出集合对象
        System.out.println(c);//[hello, my, dp]

        //boolean remove(Object o) 从集合中移除指定的元素
//        c.remove("my");
//        System.out.println(c);//[hello, dp]

        //void clear()    清空集合中的元素
//        c.clear();
//        System.out.println(c);//[]

        //boolean contains(Object o)  判断集合中是否存在指定的元素
        System.out.println(c.contains("dp"));//true
        System.out.println(c.contains("1"));//false

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

        //int size()     集合的长度,也就是集合中元素的个数
        System.out.println(c.size());//3
    }
}

1.5、Collection 集合的遍历

Iterator:迭代器,集合的专用遍历方式

  • Iterator iterator():返回此集合中元素的迭代器,通过集合的Iiterator() 方法得到
  • 迭代器是通过集合的iterator() 方法得到的,所以我们说它依赖于集合存在

Iterator中常用方法

  • E next():返回迭代中的下一个元素
  • boolean hasNext():如果迭代具有更多元素,则返回true
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class Iterator迭代器 {
    public static void main(String[] args) {
        //创建集合对象
        Collection<String> c = new ArrayList<String>();

        //添加元素
        c.add("hello");
        c.add("my");
        c.add("dp");

        //Iterator<E> iterator():返回此集合中元素的迭代器,通过集合的Iiterator() 方法得到
        Iterator<String> it = c.iterator();

        //遍历
        while (it.hasNext()){
            String s = it.next();
            System.out.println(s);
        }
    }
}

1.6、集合的使用步骤

在这里插入图片描述

2、List

2.1、List集合概述和特点

List集合概述

  • 有序集合(也称为序列),用户可以精确控制列表中每个元素的插入位置。用户可以通过整数索引访问元素,并且搜索列表中的元素
  • 与set集合不同,列表通常允许重复的元素

List集合特点:

  • 有序:存储和取出的元素顺序一致
  • 可重复 :存储的元素可以重复
/*
    list集合特点
        * ==有序==:存储和取出的元素顺序一致
        * ==可重复== :存储的元素可以重复
 */

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

public class ListDemo1 {
    public static void main(String[] args) {
        //创建集合对象
        List<String> list = new ArrayList<String>();

        //添加元素
        list.add("hello");
        list.add("my");
        list.add("dp");
        list.add("my");

        //输出集合对象
        System.out.println(list);//[hello, my, dp, my]

        System.out.println("-----------");
        
        //迭代器的方式遍历
        Iterator<String> it = list.iterator();
        while (it.hasNext()){
            String s = it.next();
            System.out.println(s);
        }

    }
}

2.3、List 集合特有方法

在这里插入图片描述

import java.util.ArrayList;
import java.util.List;

/*
    list 集合特有方法:
        void add(int index,E element)   在此集合中的指定位置插入指定的元素
        E remove(int index)     删除指定索引处的元素,返回被删除的元素
        E set(int index,E element)  修改指定索引处的元素,返回被修改的元素
        E get(int index)      返回指定索引处的元素
 */

public class ListDemo2 {

    public static void main(String[] args) {
        //创建集合对象
        List<String> list = new ArrayList<String>();

        //添加元素
        list.add("hello");
        list.add("my");
        list.add("dp");

        // void add(int index,E element)   在此集合中的指定位置插入指定的元素
        list.add(1,"hh");
        System.out.println(list);//[hello, hh, my, dp]

        // E remove(int index)     删除指定索引处的元素,返回被删除的元素
        list.remove("my");
        System.out.println(list);//[hello, hh, dp]

        // E set(int index,E element)  修改指定索引处的元素,返回被修改的元素
        list.set(1,"java");
        System.out.println(list);//[hello, java, dp]

        //E get(int index)      返回指定索引处的元素
        System.out.println(list.get(1));//java

        //用for循环来遍历
        for (int i = 0; i < list.size(); i++) {
            String s = list.get(i);
            System.out.println(s);
        }

    }
}

list 存储学生对象的集合

/*
    需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合
    思路:
        1.定义学生类
        2.创建list集合对象
        3.创建学生对象
        4.把学生添加到集合
        5.遍历集合(迭代器方式,for循环方式)
 */

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

public class ListDemo {

    public static void main(String[] args) {
        //创建list集合对象
        List<Student> list = new ArrayList<Student>();

        //创建学生对象
        Student s1 = new Student("大鹏",3);
        Student s2 = new Student("小明",3);
        Student s3 = new Student("小红",3);

        //把学生添加到集合
        list.add(s1);
        list.add(s2);
        list.add(s3);

        //迭代器方式
        Iterator<Student> it = list.iterator();
        while (it.hasNext()){
            Student s = it.next();
            System.out.println(s.getName()+","+s.getAge());
        }
        System.out.println("---------");

        //for循环
        for (int i = 0; i <list.size() ; i++) {
            Student s = list.get(i);
            System.out.println(s.getName()+","+s.getAge());
        }

    }
}

2.4、并发修改异常

/*
    需求:
        我有一个集合,list<String> list = new ArrayList<String>()
        里面有三个元素:   list.add("hello");
                        list.add("my");
                        list.add("dp");
        遍历集合,得到每一个元素,看有没有“dp”这个元素,如果有,我就添加一个“java world”元素,请写代码实现

     ConcurrentModificationException:当不允许这样的修改时,可以通过检测到对象的并发修改的方法来抛出此异常
 */


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

public class ListDemo {
    public static void main(String[] args) {
        //创建集合对象
        List<String> list = new ArrayList<String>();

        //添加元素
        list.add("hello");
        list.add("my");
        list.add("dp");

        //遍历集合,得到每一个元素,看有没有“dp”这个元素,如果有,我就添加一个“java world”元素,请写代码实现
//        Iterator<String> it = list.iterator();
//        while (it.hasNext()){
//            String s = it.next();
//            if (s.equals("dp")){
//                list.add("java world");
//            }
//        }//这样做会报错,ConcurrentModificationException

        for (int i = 0; i < list.size(); i++) {
            String s = list.get(i);
            if (s.equals("dp")){
                list.add("java world");
                System.out.println(list);
            }
        }

    }
}

2.5、ListIterator

ListIterator:列表迭代器

  • 通过List集合的ListIterator()方法得到,所以说它是list集合特有的迭代器
  • 用于允许程序员沿任一方向遍历列表的列表迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置

ListIterator中的常用方法

  • E next():返回迭代中的下一个元素
  • boolean hasNext():如果迭代具有更多元素,则返回true
  • E previous():返回列表中的上一个元素
  • boolean hasPrevious():如果此列表迭代器在相反方向遍历列表时具有更多元素,则返回true
  • void add(E e):将指定的元素插入列表
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class ListIteratorDemo {
    public static void main(String[] args) {
        //创建集合对象
        List<String> list = new ArrayList<String>();

        //添加元素
        list.add("hello");
        list.add("world");
        list.add("java");

//        //通过list集合的listIterator()方法得到
//        ListIterator<String> lit = list.listIterator();
//        while (lit.hasNext()){
//            String s = lit.next();
//            System.out.println(s);
//        }
//        System.out.println("------------");
//
//        while (lit.hasPrevious()){
//            String s = lit.previous();
//            System.out.println(s);
//        }
//        System.out.println("------------");

        //获取列表迭代器
        ListIterator<String> lit = list.listIterator();
        while (lit.hasNext()){
            String s = lit.next();
            if (s.equals("world")){
                lit.add("javaee");
            }
        }
        System.out.println(list);//[hello, world, javaee, java]
    }
}

2.6、增强for循环

增强for:简化数组和collection集合的遍历

  • 实现Iterable接口的类允许其对象成为增强for语句的目标
  • 它是JDK5之后出现的,其内部原理是一个Iterator迭代器

增强for的格式

  • 格式

for(元素数据类型 变量名:数组或者collection集合){

​ //在此处使用变量即可,该变量就是元素

}

import java.util.ArrayList;
import java.util.List;

public class ForDemo {

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

        String[] strArray = {"hello","world","java"};
        for (String s:strArray){
            System.out.println(s);
        }
        System.out.println("-----");

        //创建集合对象
        List<String> list = new ArrayList<String>();

        //添加元素
        list.add("hello");
        list.add("my");
        list.add("dp");

        for (String s:list){
            System.out.println(s);
        }
        System.out.println("-----");

        //内部原理是一个Iterator迭代器
//        for (String s:list){
//            if (s.equals("my")){
//                list.add("java");//报错ConcurrentModificationException,证明是Iterator迭代器
//            }
//        }
    }
}

2.7、List 集合子类特点

List 集合常用子类:ArrayList,LinkedList

  • ArrayList:底层数据结构是数组,查询快,增删慢
  • LinkedList:底层数据结构是链表,查询慢,增删快
import java.util.ArrayList;
import java.util.LinkedList;

public class ListDemo2 {
    public static void main(String[] args) {
        //创建集合对象
        ArrayList<String> array = new ArrayList<>();

        array.add("hello");
        array.add("world");
        array.add("java");

        //遍历
        for (String s:array){
            System.out.println(s);
        }
        System.out.println("------------");

        LinkedList<String> linkedList = new LinkedList<>();

        linkedList.add("hello");
        linkedList.add("world");
        linkedList.add("java");

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

    }
}

3、Set

3.1、Set 集合概述和特点

Set集合特点:

  • 不包含重复元素的集合
  • 没有带索引的方法,所有不能使用普通for循环遍历
/*
    Set集合特点:
* ==不包含重复元素==的集合
* ==没有带索引的方法==,所有不能使用普通for循环遍历

       HashSet:对集合的迭代顺序不作保证
 */


import java.util.HashSet;
import java.util.Set;

public class SetDemo {
    public static void main(String[] args) {
        //创建集合对象
        Set<String> set = new HashSet<>();

        //添加元素
        set.add("hello");
        set.add("world");
        set.add("java");
        //不包含重复元素的集合
        set.add("world");

        //遍历
        for (String s:set){
            System.out.println(s);
        }
    }

}

3.2、哈希值

是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值

Object类中有一种方法可以获取对象的哈希值

  • public int hashCode():返回对象的哈希值

对象的哈希值特点

  • 同一对象多次调用hashCode()方法返回的哈希值是相同的
  • 默认情况下,不同对象的哈希值是不同的,而重写hashCode()方法,可以实现让不同对象的哈希值相同

3.3、HashSet集合概述和特点

HashSet集合特点

  • 底层数据结构是哈希表
  • 对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致
  • 没有带索引的方法,所有不能使用普通for循环遍历
  • 由于是Set集合,所有是不包含重复元素的集合
import java.util.HashSet;
/*
   HashSet集合特点
* 底层数据结构是哈希表
* 对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致
* 没有带索引的方法,所有不能使用普通for循环遍历
* 由于是Set集合,所有是不包含重复元素的集合
 */
public class HashSet01 {
    public static void main(String[] args) {
        //创建集合对象
        HashSet<String> hs = new HashSet<>();

        //添加元素
        hs.add("hello");
        hs.add("world");
        hs.add("java");

        hs.add("world");

        //遍历
        for (String s:hs){
            System.out.println(s);
        }
    }
}

3.4、LinkedHashSet集合概述和特点

LinkedHashSet集合概述

  • 哈希表和链表实现的Set接口,具有可预测的迭代次序
  • 由链表保证元素有序,也就是说元素的存储和取出顺序是一致的
  • 由哈希表保证元素唯一,也就是说没有重复的元素
import java.util.LinkedHashSet;
/*
    LinkedHashSet集合概述:
* 哈希表和链表实现的Set接口,具有==可预测的迭代次序==
* 由链表保证元素有序,也就是说==元素的存储和取出顺序是一致的==
* 由哈希表保证元素唯一,也就是说==没有重复的元素==
 */
public class LinkedHashDemo {
    public static void main(String[] args) {
        //创建集合对象
        LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();

        //添加元素
        linkedHashSet.add("hello");
        linkedHashSet.add("world");
        linkedHashSet.add("java");

        linkedHashSet.add("world");

        //遍历
        for (String s:linkedHashSet){
            System.out.println(s);
        }

    }
}

3.5、TreeSet集合概述和特点

TreeSet集合特点

  • 元素有序,这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方式取决于构造方法

    TreeSet():根据其元素的自然排序进行排序

    TreeSet(Comparator comparator):根据指定的比较器进行排序

  • 没有带索引的方法,所以不能使用普通for循环遍历

  • 由于是Set集合,所以不包含重复元素的集合

/*
    TreeSet集合特点
* 元素有序,这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方式取决于构造方法
  TreeSet():根据其元素的自然排序进行排序
  TreeSet(Comparator comparator):根据指定的比较器进行排序
* 没有带索引的方法,所以不能使用普通for循环遍历
* 由于是Set集合,所以不包含重复元素的集合
 */

import java.util.TreeSet;

public class TreeSetDemo<I extends Number> {
    public static void main(String[] args) {
        TreeSet<Integer> ts = new TreeSet<Integer>();

        ts.add(10);
        ts.add(50);
        ts.add(30);
        ts.add(40);
        ts.add(80);

        ts.add(30);//不包含重复元素的集合

        for (Integer i : ts){
            System.out.println(i);
        }
    }
}

3.6、自然排序Comparable的使用

  • 存储学生对象并遍历,创建TreeSet集合使用无参构造器
  • 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序

结论:

  • 用TreeSet集合存储自定义对象,无参构造方法使用的是自然排序对元素进行排序的
  • 自然排序,就是让元素所属的类实现Comparable接口,重写compareTo(To)方法
  • 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写

注意:

当创建TreeSet集合使用无参构造器,Student类要实现Comparable接口

import java.util.TreeSet;

public class TreeSet案例 {
    public static void main(String[] args) {
        //创建集合对象
        TreeSet<Student> ts = new TreeSet<Student>();

        //创建学生对象
        Student s1 = new Student("大鹏", 25);
        Student s2 = new Student("b小明", 20);
        Student s3 = new Student("小红", 35);
        Student s4 = new Student("小慧", 15);

        Student s5 = new Student("a小刚", 20);
        Student s6 = new Student("a小刚", 20);//重复不输出

        //把学生添加到集合
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);

        ts.add(s5);
        ts.add(s6);

        //遍历集合
        for (Student s : ts){
            System.out.println(s.getName()+":"+s.getAge());
        }

    }
}


import java.util.Objects;

public class Student implements Comparable<Student>{
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Student() {
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }


    //重写hashCode()方法,可以实现让不同对象的哈希值相同
//    @Override
//    public int hashCode() {
//        return 0;
//    }


    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age && Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
    @Override
    public int compareTo(Student s){
//        return 0;//重复元素,不添加
//        return 1;//升序
//        return -1;//降序
        //按照年龄从小到大排序
        int num = this.age-s.age;//this指s2,s指s1   升序
//        int num = s.age - this.age;//降序
        //年龄相同时,按照姓名的字母顺序排序
        int num2 = num==0?this.name.compareTo(s.name):num;
        return num2;
    }
}


3.7、比较器排序Comparator的使用

  • 存储学生对象并遍历,创建TreeSet集合使用带参构造方法
  • 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
import java.util.Comparator;
import java.util.TreeSet;

public class TreeSet案例 {
    public static void main(String[] args) {
        //创建集合对象
        TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                //this.age - s.age
                //s1,s2
                int num = s1.getAge() - s2.getAge();//升序
//                int num = s2.getAge() - s1.getAge();//降序
                int num2 = num == 0? s1.getName().compareTo(s2.getName()):num;
                return num2;
            }
        });

        //创建学生对象
        Student s1 = new Student("大鹏", 25);
        Student s2 = new Student("b小明", 20);
        Student s3 = new Student("小红", 35);
        Student s4 = new Student("小慧", 15);

        Student s5 = new Student("a小刚", 20);
        Student s6 = new Student("a小刚", 20);//重复不输出

        //把学生添加到集合
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);

        ts.add(s5);
        ts.add(s6);

        //遍历集合
        for (Student s : ts){
            System.out.println(s.getName()+":"+s.getAge());
        }
    }
}


public class Student{
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Student() {
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

}

3.8、案例:成绩排序

/*
    需求:
        用TreeSet集合存储多个学生信息(姓名,语文成绩,数学成绩),并遍历该集合
        要求:按照总分从高到底出现
    思路:
        1.定义学生类
        2.创建TreeSet集合对象,通过比较器排序进行排序
        3.创建学生对象
        4.把学生对象添加到集合
        5.遍历集合
 */


import java.util.Comparator;
import java.util.TreeSet;

public class TreeSetDemo {

    public static void main(String[] args) {
        //创建TreeSet集合对象,通过比较器排序进行排序
        TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                int num = s2.getSum() - s1.getSum();
                int num2 = num ==0?s1.getChinese()-s2.getChinese():num;
                int num3 = num2 ==0?s1.getName().compareTo(s2.getName()):num2;
                return num3;
            }
        });

        //创建学生对象
        Student s1 = new Student("王杰", 90, 98);
        Student s2 = new Student("林俊杰", 98, 96);
        Student s3 = new Student("周杰伦", 96, 80);
        Student s4 = new Student("鲲远", 100, 100);
        Student s5 = new Student("旭凤", 95, 95);

        Student s6 = new Student("锦觅", 96, 94);
        Student s7 = new Student("润玉", 96, 94);

        //把学生对象添加到集合
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        ts.add(s5);

        ts.add(s6);
        ts.add(s7);

        //遍历集合
        for (Student s:ts){
            System.out.println(s.getName() +",语文成绩:"+s.getChinese()+",数学成绩:"+s.getMath()+",总分:"+s.getSum());
        }

    }

}


public class Student {
  private String name;
  private int chinese;
  private int math;

    public Student() {
    }

    public Student(String name, int chinese, int math) {
        this.name = name;
        this.chinese = chinese;
        this.math = math;
    }

    public String getName() {
        return name;
    }

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

    public int getChinese() {
        return chinese;
    }

    public void setChinese(int chinese) {
        this.chinese = chinese;
    }

    public int getMath() {
        return math;
    }

    public void setMath(int math) {
        this.math = math;
    }

    public int getSum(){
        return this.chinese+this.math;
    }
}


4、泛型

4.1、泛型概述

本质:参数化类型 ----将类型由原来的具体的类型参数化,然后在使用/调用时传入具体的类型

泛型定义格式:

  • <类型>:指定一种类型的格式。这里的类型可以看成是形参
  • <类型1,类型2…>:指定多种类型的格式,多种类型之间用逗号隔开。这里的类型可以看成是形参
  • 将来具体调用时候给定的类型可以看成是实参,并且实参的类型只能是引用数据类型

泛型的好处:

  • 把运行期间的问题提前到编译期间,更加严谨
  • 避免了强制类型转换

4.2、泛型类

定义格式:

  • 格式:修饰符 class 类名 <类型> { }
  • 范例:public class Generic{ }
    • 此处 T 可以随便写为任意标识,常见的如T、E、K、v 等形式的参数常用于表示泛型
public class GenericDemo {
    public static void main(String[] args) {
        Student s = new Student();
        s.setName("林青霞");
        System.out.println(s.getName());

        Teacher t = new Teacher();
        t.setAge(30);
        System.out.println(t.getAge());

        Generic<String> g1 = new Generic<String>();
        g1.setT("林青霞");
        System.out.println(g1.getT());

        Generic<Integer> g2 = new Generic<>();
        g2.setT(30);
        System.out.println(g2.getT());
        
        Generic<Boolean> g3 = new Generic<Boolean>();
        g3.setT(true);
        System.out.println(g3.getT());

    }
}


public class Student {
    private String name;

    public String getName() {
        return name;
    }

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


public class Teacher {
    private Integer age;

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}


public class Generic<T> {
    private T t;

    public T getT() {
        return t;
    }

    public void setT(T t) {
        this.t = t;
    }
}

4.3、泛型方法

定义格式:

  • 格式:修饰符 <类型> 返回型类型 方法名(类型 变量名){ }
  • 范例:public void show(T t){ }
public class GenericDemo {
    public static void main(String[] args) {
//        Generic g = new Generic();
//        g.show("林青霞");
//        g.show(30);
//        g.show(true);
//泛型类改进
//        Generic<String> g1 = new Generic<String>();
//        g1.show("张杰");
//
//        Generic<Integer> g2 = new Generic<Integer>();
//        g2.show(25);
//
//        Generic<Boolean> g3 = new Generic<Boolean>();
//        g3.show(true);

泛型方法改进
        Generic g = new Generic();
        g.show("张杰");
        g.show(30);
        g.show(false);


    }

}


//public class Generic {

//    public void show(String s){
//        System.out.println(s);
//    }
//
//    public  void show(Integer i){
//        System.out.println(i);
//    }
//
//    public void show(Boolean b){
//        System.out.println(b);
//    }
//}


泛型类改进
//public class Generic<T>{
//    public void show(T t){
//        System.out.println(t);
//    }
//}

//泛型方法改进
public class Generic{
    public <T> void show(T t){
        System.out.println(t);
    }
}

4.4、泛型接口

定义格式:

  • 格式:修饰符 interface 接口名<类型>{ }
  • 范例:public interface Generic{ }
public class GenericDemo {
    public static void main(String[] args) {
        Generic<String> g1 = new GenericImpl<String>();
        g1.show("林青霞");

        Generic<Integer> g2 = new GenericImpl<Integer>();
        g2.show(30);
    }
}


public interface Generic <T>{
    void show(T t);
}


public class GenericImpl <T> implements Generic<T>{
    @Override
    public void show(T t) {
        System.out.println(t);
    }
}

4.5、类型通配符

为了表示各种泛型List的父类,可以使用类型通配符

  • 类型通配符:< ? >
  • List<?>:表示元素类型未知的List,它的元素可以匹配任何类型
  • 这种带通配符的List仅表示它是各种泛型list的父类,并不能把元素添加到其中

如果说我们不希望List<?> 是任何泛型list的父类,只希望它代表某一个类泛型List的父类

  • 类型通配符上限:<? extends 类型>
  • List<? extends Number>:它表示的类型是Number或者其子类型

除了可以指定类型通配符的上限,我们也可以指定类型通配符的下限

  • 类型通配符下限:<? super 类型>
  • List<? super Number>:它表示的类型是Number或者其父类型
import java.util.ArrayList;
import java.util.List;

public class GenericDemo {
    public static void main(String[] args) {
        //类型通配符:< ? >
        List<?> list1 = new ArrayList<Object>();
        List<?> list2 = new ArrayList<Number>();
        List<?> list3 = new ArrayList<Integer>();
        System.out.println("---------");

        //类型通配符上限:<? extends 类型>  它表示的类型是<font color='red'>Number或者其子类型</font>
//        List<? extends Number> list4 = new ArrayList<Object>();//报错
        List<? extends Number> list5 = new ArrayList<Number>();
        List<? extends Number> list6 = new ArrayList<Integer>();
        System.out.println("---------");

        //类型通配符下限:<? super 类型>  它表示的类型是<font color='red'>Number或者其父类型</font>
        List<? super Number> list7 = new ArrayList<Object>();
        List<? super Number> list8 = new ArrayList<Number>();
//        List<? super Number> list9 = new ArrayList<Integer>();//报错
        
    }

}

4.6、可变参数

可变参数又称参数个数可变,用作方法的形参出现,那么方法参数个数就是可变的了

  • 格式:修饰符 返回值类型 方法名(数据类型… 变量名){ }
  • 范例:public static int sum(int… a){ }

可变参数注意事项

  • 这里的变量其实是一个数组
  • 如果一个方法有多个参数,包含可变参数,可变参数要放到最后
public class ArgsDemo01 {
    public static void main(String[] args) {
        System.out.println(sum(10,20));
        System.out.println(sum(10,20,30));
        System.out.println(sum(10,20,30,40));
        System.out.println(sum(10,20,30,40,50));

    }

//    public static int sum(int b,int... a){
//        return 0;
//    }
    
    public static int sum(int... a){
        int sum = 0;

        for (int i:a){
            sum += i;
        }
        return sum;
    }
    
//    public static int sum(int a,int b){
//        return a+b;
//    }
//
//    public static int sum(int a,int b,int c){
//        return a+b+c;
//    }
}

4.7、可变参数的使用

Arrays工具类中有一个静态方法:

  • public staticList asList(T… a):返回由指定数组支持的固定大小的列表
  • 返回的集合不能做增删改操作,可以做修改操作

List接口中有一个静态方法:

  • public static List of (E… elements):返回包含任意数量元素的不可变列表
  • 返回的集合不能做增删改操作
  • public static List of (E… elements)能用的前提是版本要是java 9[List (Java SE 9 & JDK 9 ) (oracle.com)]
    在这里插入图片描述

Set接口中有一个静态方法:

  • public static Set of(E… elements):返回一个包含任意数量元素的不可变集合
  • 在给元素的时候,不能给重复的元素
  • 返回的集合不能做增删改操作,没有修改方法
import java.util.Arrays;
import java.util.List;
import java.util.Set;

public class ArgsDemo02 {
    public static void main(String[] args) {
        //1.public static<T>List <T> asList(T... a):返回由指定数组支持的固定大小的列表
        List<String> list = Arrays.asList("hello","world","java");

//        list.add("javaee");//UnsupportedOperationException
//        list.remove("world");//UnsupportedOperationException
        list.set(1,"javaee");
        System.out.println(list); //[hello, javaee, java]

        //2.public static <E> List <E> of (E... elements):返回包含任意数量元素的不可变列表
        //of 用不了,版本要是java 9 才能用
//        List<String> list = List.of("hello", "world", "java", "world");
//        list.add("javaee");//UnsupportedOperationException
//        list.remove("world");//UnsupportedOperationException
//        list.set(1,"javaee");
//
//        System.out.println(list);

        //3.public static <E> Set <E> of(E... elements):返回一个包含任意数量元素的不可变集合
//        Set<String> set = Set.of("hello", "world", "java");
//        set.add("javaee");//UnsupportedOperationException
//        set.remove("world");//UnsupportedOperationException
//
//        System.out.println(set);

    }
}

5、Map

5.1、Map集合概述和使用

Map集合概述

  • Interface Map<K,V> k:键的类型 V:值的类型

  • 将键映射到值的对象;不能包含重复的键;每个键可以映射到最多一个值

  • 举例:学生的学号和姓名

    ​ it01 林青霞

    ​ it02 张曼玉

    ​ it03 王祖贤

创建Map集合的对象

  • 多态的方式
  • 具体的实现类HashMap
import java.util.HashMap;
import java.util.Map;

public class MapDemo01 {
    public static void main(String[] args) {
        //创建集合对象
        Map<String,String> map = new HashMap<String,String>();

        //V put(K key,V value) 将指定的值与该映射中的指定键相关联
        map.put("it01","林青霞");
        map.put("it02","张曼玉");
        map.put("it03","王祖贤");//{it02=张曼玉, it01=林青霞, it03=王祖贤}

        //输出集合对象
        System.out.println(map);


    }
}

5.2、Map集合的基本功能

在这里插入图片描述

import java.util.HashMap;
import java.util.Map;

public class MapDemo02 {
    public static void main(String[] args) {
        //创建集合对象
        Map<String,String> map = new HashMap<String,String>();

        //添加元素
        map.put("张无忌","赵敏");
        map.put("郭靖","黄蓉");
        map.put("杨过","小龙女");

        System.out.println(map);//{杨过=小龙女, 郭靖=黄蓉, 张无忌=赵敏}

        //根据键删除键值对元素
//        System.out.println(map.remove("郭靖"));//黄蓉
//        System.out.println(map.remove("郭襄"));//null
//
//        System.out.println(map);//{杨过=小龙女, 张无忌=赵敏}

        //移除所有的键值对元素
//        map.clear();

//        System.out.println(map);//{}

        //判断集合是否包含指定的键
        System.out.println(map.containsKey("郭靖"));
        System.out.println(map.containsValue("小龙女"));

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

        System.out.println(map.size());


    }
}

5.3、Map集合的获取功能

在这里插入图片描述

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class MapDemo03 {
    public static void main(String[] args) {
        //创建集合对象
        Map<String,String> map = new HashMap<String,String>();

        //添加元素
        map.put("张无忌","赵敏");
        map.put("郭靖","黄蓉");
        map.put("杨过","小龙女");

        //根据键获取值
        System.out.println(map.get("张无忌"));//赵敏
        System.out.println(map.get("张三丰"));//null

        //Set< K > keyset():获取所有键的集合
        Set<String> keyset = map.keySet();
        for (String key:keyset){
            System.out.println(key);
        }

        //Collection<V> values():获取所有值的集合
        Collection<String> values = map.values();
        for (String value:values){
            System.out.println(value);
        }


    }
}

5.4、Map集合的遍历(方式1)

我们刚才存储的元素都是成对出现的,所以我们把Map看成是一个夫妻对的集合

遍历的思路

  • 把所有的丈夫给集中起来
  • 遍历丈夫的集合,获取到每一个丈夫
  • 根据丈夫去找对应的妻子

转换为Map集合中的操作:

  • 获取所有键的集合,用keySet()方法实现
  • 遍历键的集合,获取到每一个键,用增强for实现
  • 根据键去找值,用get(Object key)方法实现
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class MapDemo01 {
    public static void main(String[] args) {
        //创建集合对象
        Map<String,String> map = new HashMap<String,String>();

        //添加元素
        map.put("张无忌","赵敏");
        map.put("郭靖","黄蓉");
        map.put("杨过","小龙女");

        //获取所有键的集合。用keySet()方法实现
        Set<String> keyset = map.keySet();
        //遍历键的集合,获取到每一个键。用增强for实现
        for (String key:keyset){
            //根据键去找值。用get(Object key)方法实现
            String value = map.get(key);
            System.out.println(key+","+value);
        }

    }

}

5.5、Map集合的遍历(方式2)

我们刚才存储的元素都是成对出现的,所以我们把Map看成是每一个夫妻对的集合

遍历思路:

  • 获取所有结婚证的集合
  • 遍历结婚证的集合,得到每一个结婚证
  • 根据结婚证获取丈夫和妻子

转换为Map集合中的操作

  • 获取所有键值对对象的集合

    Set<Map.Entry<K,V> >entrySet()

  • 遍历键值对对象的集合,得到每一个键值对对象

    用增强for实现,得到每一个 Map.Entry

  • 根据键值对对象获取键和值

    • getKey( )得到键
    • getValue得到值
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class MapDemo02 {
    public static void main(String[] args) {
        //创建集合对象
        Map<String,String> map = new HashMap<String,String>();

        //添加元素
        map.put("张无忌","赵敏");
        map.put("郭靖","黄蓉");
        map.put("杨过","小龙女");

        //获取所有键值对对象的集合
        Set<Map.Entry<String, String>> entrySet = map.entrySet();
        //遍历键值对对象的集合,得到每一个键值对对象
        for (Map.Entry<String, String> me:entrySet){
            //根据键值对对象获取键和值
            String key = me.getKey();
            String value = me.getValue();
            System.out.println(key+","+value);
        }

    }
}

5.6、案例:HashMap集合存储学生对象并遍历

在这里插入图片描述

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class HashMapDemo {
    public static void main(String[] args) {
        //创建HashMap集合对象
        HashMap<String, Student> hm = new HashMap<String, Student>();

        //创建学生对象
        Student s1 = new Student("林青霞",30);
        Student s2 = new Student("张曼玉",35);
        Student s3 = new Student("王祖贤",33);

        //把学生添加到集合
        hm.put("IT01",s1);
        hm.put("IT02",s2);
        hm.put("IT03",s3);

        //方式1:键找值
        Set<String> keySet = hm.keySet();
        for (String key:keySet){
            Student value = hm.get(key);
            System.out.println(key+","+value.getName()+","+value.getAge());
        }

        //方式2:键值对对象找键和值
        Set<Map.Entry<String, Student>> entrySet = hm.entrySet();
        for (Map.Entry<String, Student> me:entrySet){
            String key = me.getKey();
            Student value = me.getValue();
            System.out.println(key+","+value.getName()+","+value.getAge());

        }

    }
}

public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}


在这里插入图片描述

import java.util.HashMap;
import java.util.Set;

public class HashMapDemo02 {
    public static void main(String[] args) {
        //创建HashMap集合对象
        HashMap<Student, String> hm = new HashMap<>();

        //创建学生对象
        Student s1 = new Student("林青霞",30);
        Student s2 = new Student("张曼玉",35);
        Student s3 = new Student("王祖贤",33);
        Student s4 = new Student("王祖贤",33);

        //把学生添加到集合
        hm.put(s1,"西安");
        hm.put(s2,"武汉");
        hm.put(s3,"郑州");
        hm.put(s4,"北京");//王祖贤的地点从郑州变成北京,需要重写hashCode(),equals()这两个方法,不然会出现两个王祖贤

        //遍历集合
        Set<Student> keySet = hm.keySet();
        for (Student key:keySet){
            String value = hm.get(key);
            System.out.println(key.getName()+","+key.getAge()+","+value);
        }


    }

}


import java.util.Objects;

public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age && Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

5.7、ArrayList集合存储HashMap元素并遍历

在这里插入图片描述

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;

public class ArrayListIncludeHashMapDemo {
    public static void main(String[] args) {
        //创建ArrayList集合
        ArrayList<HashMap<String, String>> array = new ArrayList<HashMap<String, String>>();

        //创建HashMap集合,并添加键值对元素
        HashMap<String, String> hm1 = new HashMap<>();
        hm1.put("孙策","大乔");
        hm1.put("周瑜","小乔");
        //把HashMap作为元素添加到ArraryList集合
        array.add(hm1);

        HashMap<String, String> hm2 = new HashMap<>();
        hm2.put("郭靖","黄蓉");
        hm2.put("杨过","小龙女");
        //把HashMap作为元素添加到ArraryList集合
        array.add(hm2);

        HashMap<String, String> hm3 = new HashMap<>();
        hm3.put("令狐冲","任盈盈");
        hm3.put("林平之","岳灵珊");
        //把HashMap作为元素添加到ArraryList集合
        array.add(hm3);

        //遍历ArrayList集合
        for (HashMap<String, String> hm:array){
            Set<String> keySet = hm.keySet();
            for (String key:keySet){
                String value = hm.get(key);
                System.out.println(key+","+value);
            }
        }


    }
}

在这里插入图片描述

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;

public class HashMapIncludeArrayListDemo {
    public static void main(String[] args) {
        //创建HashMap集合
        HashMap<String, ArrayList<String>> hm = new HashMap<>();

        //创建ArrayList集合,并添加元素
        ArrayList<String> sgyy = new ArrayList<>();
        sgyy.add("诸葛亮");
        sgyy.add("赵云");
        //把ArrayList作为元素添加到HashMap集合
        hm.put("三国演义",sgyy);

        ArrayList<String> xyj = new ArrayList<>();
        xyj.add("唐僧");
        xyj.add("孙悟空");
        //把ArrayList作为元素添加到HashMap集合
        hm.put("西游记",xyj);

        ArrayList<String> shz = new ArrayList<>();
        shz.add("武松");
        shz.add("鲁智深");
        //把ArrayList作为元素添加到HashMap集合
        hm.put("水浒传",shz);

        //遍历HashMap集合
        Set<String> keySet = hm.keySet();
        for (String key:keySet){
            System.out.println(key);
            ArrayList<String> value = hm.get(key);
            for (String s:value){
                System.out.println("    "+s);
            }
        }

    }
}

6、Collections

6.1、Collections概述和使用

Collections类的概述

  • 是针对集合操作的工具类

Collections类的常用方法

  • public static<T extends Comparable<? super T>> void sort (List list):将指定的列表按升序排序
  • public static void reverse(List<?> list):反转指定列表中元素的顺序
  • public static void shuffle(List <?> list):使用默许的随机源随机排列指定的列表
import java.util.ArrayList;
import java.util.Collections;

public class CollectionsDemo {
    public static void main(String[] args) {
        //创建集合对象
        ArrayList<Integer> list = new ArrayList<Integer>();

        //添加元素
        list.add(30);
        list.add(10);
        list.add(50);
        list.add(20);
        list.add(40);

        //public static<T extends Comparable<? super T>>  void sort (List<T> list):将指定的列表按升序排序
//        Collections.sort(list);
//        System.out.println(list);//[10, 20, 30, 40, 50]

        //public static void reverse(List<?> list):反转指定列表中元素的顺序
//        Collections.reverse(list);
//        System.out.println(list);//[40, 20, 50, 10, 30]

        //public static void shuffle(List <?> list):使用默许的随机源随机排列指定的列表
        Collections.shuffle(list);
        System.out.println(list);//[20, 30, 10, 50, 40]


    }
}

6.2、案例:ArrayList存储学生对象并排序

在这里插入图片描述

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class CollectionsDemo02 {
    public static void main(String[] args) {
        ArrayList<Student> array = new ArrayList<Student>();

        //创建学生对象
        Student s1 = new Student("林青霞",30);
        Student s2 = new Student("张曼玉",35);
        Student s3 = new Student("王祖贤",33);

        //把学生添加到集合
        array.add(s1);
        array.add(s2);
        array.add(s3);

        //使用Collections对ArrayList集合排序
        //sort (List<T> list,Comparator<? super T> c)
        Collections.sort(array, new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                //按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
                int num = s1.getAge() - s2.getAge();
                int num2 = num ==0?s1.getName().compareTo(s2.getName()):num;
                return num2;
            }
        });

        //遍历集合
        for (Student s:array){
            System.out.println(s.getName()+","+s.getAge());
        }

    }
}

.util.ArrayList;
import java.util.Collections;

public class CollectionsDemo {
public static void main(String[] args) {
//创建集合对象
ArrayList list = new ArrayList();

    //添加元素
    list.add(30);
    list.add(10);
    list.add(50);
    list.add(20);
    list.add(40);

    //public static<T extends Comparable<? super T>>  void sort (List<T> list):将指定的列表按升序排序

// Collections.sort(list);
// System.out.println(list);//[10, 20, 30, 40, 50]

    //public static void reverse(List<?> list):反转指定列表中元素的顺序

// Collections.reverse(list);
// System.out.println(list);//[40, 20, 50, 10, 30]

    //public static void shuffle(List <?> list):使用默许的随机源随机排列指定的列表
    Collections.shuffle(list);
    System.out.println(list);//[20, 30, 10, 50, 40]


}

}




### 6.2、案例:ArrayList存储学生对象并排序

[外链图片转存中...(img-faxCj86k-1630291556995)]



```java
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class CollectionsDemo02 {
    public static void main(String[] args) {
        ArrayList<Student> array = new ArrayList<Student>();

        //创建学生对象
        Student s1 = new Student("林青霞",30);
        Student s2 = new Student("张曼玉",35);
        Student s3 = new Student("王祖贤",33);

        //把学生添加到集合
        array.add(s1);
        array.add(s2);
        array.add(s3);

        //使用Collections对ArrayList集合排序
        //sort (List<T> list,Comparator<? super T> c)
        Collections.sort(array, new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                //按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
                int num = s1.getAge() - s2.getAge();
                int num2 = num ==0?s1.getName().compareTo(s2.getName()):num;
                return num2;
            }
        });

        //遍历集合
        for (Student s:array){
            System.out.println(s.getName()+","+s.getAge());
        }

    }
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值