Java教程

还不知道Java容器集合的基础知识?——看过来,通俗易懂

本文主要是介绍还不知道Java容器集合的基础知识?——看过来,通俗易懂,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

目录

  • 前言
  • 一、Collection集合
    • 1.1、List集合
      • 1.1.1、ArrayList集合
      • 1.1.2、LinkedList集合
      • 1.1.3、并发修改异常
      • 1.1.4、ListIterator
      • 1.1.5、增强for
      • 1.1.6、数据结构
    • 1.2、Set集合
      • 1.2.1、哈希值
      • 1.2.2、HashSet集合
      • 1.2.3、TreeSet集合
  • 二、Map集合
    • 2.1、Map集合的概述以及创建
    • 2.2、Map集合的基本功能
    • 2.3、Map集合的遍历
    • 2.4、HashMap集合
  • 三、Collections类
  • 四、泛型
    • 4.1、泛型类
    • 4.2、泛型方法
    • 4.3、泛型接口
    • 4.4、类型通配符
    • 4.5、可变参数

前言

本篇博客分享的是java中常用的容器集合,大体分为了两类(Collection单列集合和Map双列集合),什么是双列,单列集合呢?看完这篇博客,或许你将有些许收获。Collection集合下主要讲解List集合和Set集合,而双列集合,我主要讲解HashMap集合。

在这里插入图片描述

一、Collection集合

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

  • 创建Collection集合的对象:多态的方式
    具体的实现类ArrayList: Collection c = new ArrayList ();

  • 常用方法
    在这里插入图片描述
    Alt + 7 打开一个窗口,能够看到类的所有信息
    add返回true
    clear 清空集合中所有的元素

  • 遍历:
    Iterator:迭代器,集合的专用遍历方式
    Iterator iterator () ; 返回次集合中元素的迭代器,通过集合的iterator () 方法得到
    迭代器是通过集合的iterator ()方法得到的,所以说我们说它是依赖于集合而存在的

    Iterator中的常用方法:
    E next():返回迭代中的下一个元素
    boolean hasNext():如果迭代具有更多元素,则返回true

    NoSuchElementException:表示请求的元素不存在
    下面展示一些 内联代码片

Iterator遍历代码实现
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class test {
    public static void main(String[] args) {
        Collection<Student> c=new ArrayList<Student>();
        Student s1=new Student("秦潇",21);
        Student s2=new Student("王霖兴",22);

        c.add(s1);
        c.add(s2);

        Iterator<Student> it = c.iterator();

        while (it.hasNext()){
            Student s = it.next();
            System.out.println(s.getName()+","+s.getAge());

        }
    }
}

1.1、List集合

  • 概述:
    有序集合(也称为序列),用户可以精确控制列表中每个元素的插入位置,用户可以通过整数索引访问元素
    与Set集合不同,列表通常允许重复的元素
  • 特点
    有序:存储和取出的元素顺序一致
    可重复:存储的元素可以重复
  • 特有方法:
    在这里插入图片描述
  • 遍历:
    for循环,利用get方法,get(i);
List集合遍历的代码实现
//学生类
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;
    }
}
 
//--------------------------------------------------------
//测试类
public class ListDemo {
    public static void main(String[] args) {
        //创建List集合对象
        List<Student> list = new ArrayList<Student>();
 
        //创建学生对象
        Student s1 = new Student("秦潇", 21);
        Student s2 = new Student("魏涛", 21;
        Student s3 = new Student("朱帅", 23);
 
        //把学生添加到集合
        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());
        }
        System.out.println("--------");
 
        //增强for:最方便的遍历方式
        for(Student s : list) {
            System.out.println(s.getName()+","+s.getAge());
        }
    }
}

1.1.1、ArrayList集合

ArrayList集合是List集合的实现类,它的底层是数组结构实现,查询快、增删慢,它的一些常用方法可以参考List集合的常用方法。

1.1.2、LinkedList集合

LinkedList集合是List集合的实现类,它的底层是链表结构实现,查询慢、增删快,它有一些特有的常用方法

  • LinkedList集合特有功能
    在这里插入图片描述

1.1.3、并发修改异常

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

  • 产生原因:
    我们在通过迭代器遍历的过程中,通过集合去添加了元素,就造成了迭代器在获取元素的时候里面进行判断这个预期修改的值,和实际修改的值不一致的情况,这样就造成了并发修改异常

  • 解决方案

    用for循环遍历,用集合对象做相应的操作即可

1.1.4、ListIterator

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

1.1.5、增强for

  • 目的:
    简化数组和Collection集合的遍历

  • 格式:
    在这里插入图片描述
    在这里插入图片描述
    原理就是一个Iterator迭代器

1.1.6、数据结构

  • 概念:
    数据结构是计算机存储、组织数据的方式。是值相互之间存在一种或多种特定关系的数据元素的集合

  • 目的:
    通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率

  • 栈:
    先进后出

  • 队:
    先进先出

  • 数组结构:
    增删慢
    查询快

  • 链表结构:
    增删快
    查询慢

1.2、Set集合

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

  • 创建
    例如:
    Set set = new HashSet();

1.2.1、哈希值

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

  • 获取哈希值:
    Object类中有一个方法可以获取对象的哈希值
    public int hashCode():返回对象的哈希码值

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

  • 哈希表:
    在JDK8之前,底层采用数组+链表实现,可以说是一个元素为链表的数组
    在JDK8以后,在长度比较长的时候,底层实现了优化

1.2.2、HashSet集合

  • 特点:
    底层数据结构是哈希表。
    对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致。
    没有带索引的方法,所以不能使用普通for循环遍历。
    由于是Set集合,所以是不包含重复元素的集合。
  • 添加一个元素的过程:

在这里插入图片描述

  • 存储元素:
    要确保元素唯一性,需要重写hashCode()和equals()方法
  • 注意:
    HashSet: 对集合的迭代顺序不作任何保证
  • 拓展:LinkedHashSet
  • LinkedHashSet集合特点:
    哈希表和链表实现的Set接口,具有可预测的迭代次序
    由链表保证元素有序,也就是说元素的存储和取出顺序是一致的
    由哈希表保证元素唯一,也就是说没有重复的元素

1.2.3、TreeSet集合

  • 特点
    1、元素有序,这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方式取决于构造方法
    TreeSet():根据其元素的自然排序进行排序
    TreeSet(Comparator comparator):根据指定的比较器进行排序

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

    3、由于是Set集合,所以不包括重复元素的集合

要理解好TreeSet必须先了解自然排序Comparable:

  • 案例需求:

    存储学生对象并遍历,创建TreeSet集合使用无参构造方法

  • 要求:

    按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序

  • 实现步骤:

    用TreeSet集合存储自定义对象,无参构造方法使用的是自然排序对元素进行排序的

    自然排序,就是让元素所属的类实现Comparable接口,重写compareTo(T o)方法

    重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写

案例代码实现
public class Student implements Comparable<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 int compareTo(Student s) {
//        return 0;
//        return 1;
//        return -1;
        //按照年龄从小到大排序
       int num = this.age - s.age;
//        int num = s.age - this.age;
        //年龄相同时,按照姓名的字母顺序排序
       int num2 = num==0?this.name.compareTo(s.name):num;
        return num2;
    }
}
//------------------------------------------------
public class TreeSetDemo02 {
    public static void main(String[] args) {
        //创建集合对象
        TreeSet<Student> ts = new TreeSet<Student>();
 
        //创建学生对象
        Student s1 = new Student("qinxiao", 21);
        Student s2 = new Student("wanglinxing", 21);
        Student s3 = new Student("weitao", 20);
        Student s4 = new Student("zhushuai", 23);
 
        Student s5 = new Student("liguang",22);
        Student s6 = new Student("longzeguo",23);
 
        //把学生添加到集合
        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());
        }
    }
}

比较器排序Comparator的使用:

  • 案例需求:

    存储学生对象并遍历,创建TreeSet集合使用带参构造方法

  • 要求:

    按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序

  • 实现步骤

    用TreeSet集合存储自定义对象,带参构造方法使用的是比较器排序对元素进行排序的

    比较器排序,就是让集合构造方法接收Comparator的实现类对象,重写compare(T o1,T o2)方法

    重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写

案例代码实现
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;
    }
}
//===================================================================
public class TreeSetDemo {
    public static void main(String[] args) {
        //创建集合对象
        TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                //this.age - s.age
                //s1,s2
                int num = s1.getAge() - s2.getAge();
                int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
                return num2;
            }
        });
 
        //创建学生对象
        Student s1 = new Student("qinxiao", 21);
        Student s2 = new Student("wanglinxing", 21);
        Student s3 = new Student("weitao", 20);
        Student s4 = new Student("zhushuai", 23);
 
        Student s5 = new Student("liguang",22);
        Student s6 = new Student("longzeguo",23);
 
        //把学生添加到集合
        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());
        }
    }
}

二、Map集合

2.1、Map集合的概述以及创建

  • Map集合概述:

    Interfacce Map <K,V> K:键的类型 V:值的类型

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

    举例:学生的学号和姓名
    itheima001 林青霞

  • 创建Map集合的对象:

    多态的方式

    具体的实现类HashMap

2.2、Map集合的基本功能

  • 基本功能

在这里插入图片描述

  • Map集合的获取功能
    在这里插入图片描述

2.3、Map集合的遍历

  • 思路1:

    获取所有键的集合,用keySet()方法实现

    遍历键的集合,获取到每一个键,用增强for实现

    根据键去找值,用get(Object key)方法实现
    在这里插入图片描述

  • 思路2

    获取所有键值对对象的集合
    Set<Map.Entry<K,V>> entrySet():获取所有键值对对象的集合

    遍历键值对对象的集合,得到每一个键值对对象
    用增强for实现,得到每一个Map.Entry

    根据键值对对象获取键和值
    用getKey( )得到键
    用getValue( )得到值
    在这里插入图片描述

2.4、HashMap集合

HashMap是Map的实现类,HashMap可实现快速存储和检索,但缺点是包含的元素是无序的,适用于在Map中插入、删除和定位元素。常用方法参考Map集合。

三、Collections类

  • 概述:

    是针对集合操作的工具类

  • 常用方法:
    在这里插入图片描述

四、泛型

  • 泛型概念:

    是JDK5中引入的特性,它提供了编译时类型安全检测机制,该机制允许在编译时检测到非法的类型

    它本质是参数化类型,也就是说所操作的数据类型被指定为一个参数

  • 参数化类型概念:

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

    这种参数类型可以用在类、方法和接口中,分别被称为泛型类、泛型方法、泛型接口

  • 泛型定义格式:

    <类型>:指定一种类型的格式。这里的类型可以看成是形参

    <类型1,类型2…>:指定多种类型的格式,多种类型之间用逗号隔开。这里的类型可以看成是形参

    将来具体调用时候给定的类型可以看成是实参,并且实参的类型只能是引用数据类型

  • 泛型的好处

    将运行时期的问题提前到了编译期间

    避免了强制类型的转换

4.1、泛型类

  • 格式:

    修饰符 class 类名 <类型>{ }

    范例:
    public class Generic { }

    此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数用于表达泛型

4.2、泛型方法

  • 格式:

    修饰符 <类型> 返回值类型 方法名 (类型 变量名) { }

    范例:

    public void show(T t){ }

4.3、泛型接口

  • 格式:

    修饰符 interface 接口名 <类型> { }

    范例:

    public interface Generic { }

4.4、类型通配符

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

类型通配符 <?>

List <?> 表示元素类型未知的List,它的元素可以匹配任何的类型

这种带通配符的List仅表示它是各种泛型List的父类,并不能吧元素添加到其中

  • 类型通配符上限:

    <? extends 类型>

    List<?extends Number >:它表示的类型是Number或者其子类类类型

    我们不希望List <?>是任何泛型List 的父类,只希望它代表某一类泛型List的父类,可以使用类型通配符的上限

  • 类型通配符下限:

    <? super 类型>

    List <? super Number> :它表示的类型是Number或者其父类类型

4.5、可变参数

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

  • 注意事项:

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

    这里的变量其实是一个数组, 如a

    如果一个方法有多个参数,包含可变参数,可变参数要放在最后

  • 使用:

  • Arrays

    public static List asList(T… a):返回由指定数组支持的固定大小的列表

     返回的集合不能做增删操作,可以做修改的操作
    
  • List

    public static List of (E… elements): 返回包括任意数量元素的不可变列表

    返回的集合不能做增删改操作

  • Set

    public static Set of (E… elements): 返回一个包含任意数量元素的不可变集合

    在给元素的时候,不能给重复的元素

    返回的集合不能做增删操作,没有修改的方法

这篇关于还不知道Java容器集合的基础知识?——看过来,通俗易懂的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!