集合类

Java集合类

0. 学习目标

  1. 会使用集合存储数据
  2. 会遍历集合,把数据取出来
  3. 掌握每种集合的特性

0. 集合的框架

1. Collection

1.1 概述

collection是所有单列集合的最顶层的接口,定义了所有单列集合共性的方法

1.2 常用方法

方法返回类型功能
add(E e)boolean添加元素
clear()void清空集合
remove(E e)boolean移除元素
contains(E e)boolean判断是否包含元素
isEmpty()boolean判断集合是否为空
size()int集合中元素个数
toArray()Object[]把集合中的元素储存到数组中

2. Iterator(迭代器)

2.1 概述

  • 迭代:Collection集合元素的通用获取方式。再取元素之前先要判断集合中是否有元素,有则取,直至所有元素被取出。
  • 用于对集合进行遍历
  • Iterator是一个接口,无法直接使用,需要使用该接口的实现类对象,获取实现类的方式比较特殊,Cellection接口中有一个iterator()方法,即返回迭代器的实现类对象。
  • 迭代器的使用步骤
    • 先使用集合中的方法iterator()获取迭代器的实现类对象,使用Iterator接口接收(多态)
    • 使用Iterator接口中的方法hanNext()判断是否有下一个元素
    • 使用Iterator接口中的方法next()获取下一个方法
Collection<String> coll = new ArrayList<>();
coll.add("1");
coll.add("2");
Iterator<String> it = coll.iterator();
while (it.hasNext()) {
    System.out.println(it.next());
}
  • 实现原理:初始指针索引为-1,通过hasNext()判断集合中是否有下一个元素,通过next()返回下一个元素,并把指针向后移动一位

2.2 常用方法

方法返回类型功能
next()E返回迭代的元素
hasNext()boolean判断是否有元素可以迭代

3. 泛型

3.1 概述

  • 泛型是一种未知的数据类型,在不知道使用何种数据类型时,可使用泛型

  • 泛型可看作一个变量,用来接收数据类型

    • E e : Element元素
    • T t : Type类型
    public class ArrayList<E> {
    	public boolean add(E e) {};
    	public E get(int index) {};
    }
    
  • 创建集合对象的时候,确定泛型的类型。即把数据类型作为参数传递给泛型E。

3.2 对比

  • 不使用泛型
    • 好处:集合默认类型为Object类型,可以存储任意类型的数据
    • 坏处:不安全,会引发异常
  • 使用泛型
    • 好处:避免类型转换的麻烦;把运行期异常(代码运行后抛出的异常)提升到了编译期(写代码的时候会报错)
    • 坏处:只能存储单一类型的数据,由创建对象时指定

3.3 泛型的定义与使用

/* 
	定义含有泛型的类
	在不确定使用什么数据类型的时候,使用泛型
	泛型可以接受任意的数据类型
	创建对象时确定泛型的数据类型
*/
public class Student<E> {
    private E name;

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

/*
	定义含有类型的方法
	泛型定义在方法的修饰符和返回值类型之间
	格式:
		修饰符 <泛型> 返回值类型 方法名(参数列表) {
			方法体;
		}
	含有泛型的方法,在调用方法时确定泛型的数据类型
*/
public class Student {
	// 含有泛型的方法
    public <M> void method1(M m) {
        System.out.println("1" + m);
    }
	// 含有泛型的静态方法
    public static <M> void method2(M m) {
        System.out.println("2" + m);
    }
	
    public static void main(String[] args) {
        Student st = new Student();
        // 使用含有泛型的方法
        st.method1(11);
        st.method1("hello");
        st.method1(2.5);
        Student.method2(996);
        Student.method2("world");
    }
}

/*
	定义含有泛型的接口
*/
public interface Person<I> {
    void method(I i);
}
/*
    第一种使用方法:定义接口的实现类,指定接口的类型
 */
public class Student implements Person<String> {
    public void method(String str) {
        System.out.println(str);
    }

    public static void main(String[] args) {
        Student st = new Student();
        st.method("hello");
    }
}
/*
    第二种使用方法:接口使用什么泛型,实现类就使用什么泛型,即类跟着接口走
    相当于定义了一个含有泛型的类,创建对象时确定泛型的数据类型
 */
public class Student<I> implements Person<I> {
    public void method(I i) {
        System.out.println(i);
    }

    public static void main(String[] args) {
        Student<Integer> st = new Student<>();
        st.method(1024);
    }
}

3.4 泛型通配符

  • 当使用泛型类或者接口时,传递的数据中泛型类型不确定,可使用通配符<?>表示。一旦使用泛型通配符,则只能使用Object类中的共性方法
  • 使用通配符,则只能接收数据,不能往该集合中存储数据
/*
    泛型通配符
    使用方式:
        不能创建对象使用
        只能作为方法的参数使用
 */
public class Student {

    public static void main(String[] args) {
        ArrayList<Integer> list1 = new ArrayList<>();
        ArrayList<String> list2 = new ArrayList<>();
        list1.add(1);
        list1.add(2);
        list2.add("hello");
        list2.add("world");
        printArray(list1);
        printArray(list2);
    }

    // 定义一个方法,可遍历所有类型的ArrayList集合
    public static void printArray(ArrayList<?> list) {
        Iterator<?> it = list.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
    }
}
java
  • 通配符高级使用——受限泛型
    • Java的泛型可以指定上限和下限
    • 上限
      • 格式:类型名称 <? extends 类> 对象名称
      • 意义:只可接收该类型及其子类型
    • 下限
      • 格式:类型名称 <? super 类> 对象名称
      • 意义:只可接收该类型及其父类型

4. 相关数据结构

4.1 栈

  • 先进后出

4.2 队列

  • 先进先出

4.3 数组

  • 查询快:数组的地址时连续的,可以通过数组的首地址和索引快速查找一个元素
  • 增删慢:数组长度是固定的,增删一个元素,必须创建一个新数组,把数组的数据复制过来

4.4 链表

  • 查询慢:地址不连续,每次查询都需要从头部开始
  • 增删快:对链表的整体结构没有影响
  • 单向链表:只有一条链,不保证元素的顺序
  • 双向链表:有两条链,有一条链专门记录元素的顺序,是一个有序的集合

4.5 红黑树

  • 特点:趋近于平衡树,查询速度非常快,查询叶子节点最大次数和最小次数不能超过2倍
  • 约束
    • 节点可以是黑色的,可以是红色的
    • 根节点是黑色的
    • 叶子节点(空节点)是黑色的
    • 每个红色节点的子节点都是黑色的
    • 任何一个节点到其每一个叶子节点的所有路径上黑色节点数量相同

5. List

5.1 概述

  • 特点
    • 有序
    • 有索引
    • 允许重复的元素

5.2 常用方法

方法返回类型功能
add(int index, E element)void将指定的元素添加到指定位置
get(int index)E返回指定位置的元素
remove(int index)E移除指定位置的元素,返回被移除的元素
set(int index, E element)E用指定元素替换指定位置的元素,返回被替代的元素

5.3 遍历方式

// 普通for循环
for (int i = 0; i < list.size(); i++) {...}
// 迭代器
Iterator<E> it = list.iterator();
while (it.hasNext) {...}
// 增强for循环
for (E e : list) {...}

5.4 实现类

5.4.1 ArrayList
  • List接口的大小可变的数组实现,此实现不是同步的(多线程,速度快)
  • 增删慢,查询快
  • 方法的实现方式
    • add:复制数组,长度加一,添加元素
5.4.2 LinkedList
  • 接口的链接列表实现,此实现不是同步的

  • 是一个双向链表

  • 查询慢,增删快

  • 使用LinkedList特有的方法时,不能使用多态

    • 方法返回类型功能
      addFirst(E e)void将指定元素插入到列表开头
      addLast(E e)void将指定元素插入到列表结尾,等效于add(E e)
      push(E e)void将元素推入列表所表示的堆栈,等效于addFirst(E e)
      getFirst()E返回列表第一个元素(为空报错)
      getLast()E返回列表最后一个元素(为空报错)
      removeFirst()E移除并返回列表第一个元素
      removeLast()E移除并返回列表最后一个元素
      pop()E从列表表示的堆栈中弹出一个元素,等效于removeFirst()
5.4.3 Vector
  • 可以实现可增长的对象数组。底层是一个数组,是同步的(单线程,速度慢)
  • 历史悠久,目前很少用

6. Set

6.1 概述

  • 继承了Collection接口
  • 特点
    • 不允许存储重复元素
    • 没有索引

6.2 实现类

6.2.1 HashSet
  • 是一个无序的集合
  • 底层是一个哈希表,查询速度非常快
  • 哈希值
    • 是一个十进制的整数,由系统随即给出(就是对象的地址,逻辑地址)
    • int hashCode():返回对象的哈希值
  • 哈希表(存储数据的结构)
    • JDK1.8前,哈希表=数组+链表
    • JDK1.8后,哈希表=数组+链表+红黑树(提高查询速度)
      • 数组把元素进行分组,相同哈希值的元素为一组
      • 链表/红黑树把相同哈希值的元素连接到一起
    • 特点:查询速度快
    • 初始容量为16
    • 原理
      • 存储数据到集合中,先计算元素的哈希值,然后找到数组中对应的哈希值,并插在对应链表中。在JDK1.8后,如果一个链表长度超过了8,就将其转化为一个红黑树(提高查询速度)
  • Set集合不允许重复元素的原理
    • 调用add方法时,会调用hashCode和equals方法,判断元素是否重复
    • 若未重复(重复:哈希值相等,且调用equals返回true),则存储到集合
    • 若重复,则不存储
  • HashSet存储自定义类型元素
    • 需要重写hashCode方法和equals方法,保证哈希值不唯一
6.2.3 LinkedHashSet
  • 继承了HashSet,实现了Set接口
  • 具有可预知的迭代顺序
  • 底层是一个哈希表+链表,多的一条链表用来记录元素的存储顺序,从而保证有序

7. Collections工具类

7.1 常用功能

方法返回类型功能
addAll(Collection c, T…elements)boolean一次性添加多个元素
shuffie(List<?> list)void打乱顺序
sort(List list)void将元素按默认规则排序(升序)
sort(List list, Comparator<? super T>)void将元素按指定的规则排序
  • sort注意
    • 使用前存储的元素类需要实现Comparable接口
    • 排序规则:this在前为升序,在后为降序
  • Comparator与Comparable比较
    • Comparable:自己和别人比较,需要实现compareTo()方法
    • Comparator:找一个第三方的裁判进行比较,需要重写compare(T o1, T o2)方法
      • o1 - o2 升序,o2 - o1 降序

8. Map

8.1 概述

  • Map<K, V>
  • 将键映射到值的对象。不可包含重复的键,每个键最多只能映射到一个值。

8.2 实现类

8.2.1 HashMap
  • HashMap<K, V>

  • 不同步,多线程,速度快

  • 特点

    • 底层是哈希表,查询速度快
    • 无序
  • 子类——LinkedHashMap

    • 特点
      • 底层是哈希表+链表
      • 有序
  • 常用方法

    • 方法返回类型功能
      put(K key, V value)V添加键值对(key, value),若key不重复,则返回null,若重复,则用新的value替换旧的value,并返回旧的value
      remove(Object key)V根据key把指定键值对元素删除,并返回被删除的元素的value,若key不存在,则返回null
      get(Object key)V根据key获得value,若key不存在,返回null
      containsKey(Object key)boolean判断是否含有键key
      keySet()Set(K)返回Map集合中的所有键key组成的集合
      entrySet()Set<K, V>返回Map集合中所有键值对<key, value>组成的集合
  • Map.Entry(键—值对)

    • 作用:当Map集合一创建,便会再Map集合中创建Entry对象,记录键和值(键值对对象)
    • 方法
      • getKey():获取值
      • getValue():获取键
  • 存储自定义对象

    • 作为key时,必须重写hashCode和equals方法,保证key唯一
8.2.2 Hashtable
  • key和value不能为null
  • 同步,单线程,速度慢
  • 和vector集合一样,在1.2版本后被更先进的集合类取代了
  • 其子类Properties集合依然活跃,是一个唯一和IP流结合的集合

9 补充

9.1 JDK9对添加元素的优化

  • list接口、Set接口、Map接口增加了静态方法op(E… element),可以给集合一次性添加多个元素

  • 使用前提

    • 集合中存储的元素个数已经确定、不再改变的时候可以使用
  • 注意

    • of方法只适用于list接口、Set接口、Map接口,不适用于接口的实现类
    • of方法返回值是不能改变的集合,若对集合进行修改(如add,remove),则抛出异常
  • getValue():获取键

  • 存储自定义对象

    • 作为key时,必须重写hashCode和equals方法,保证key唯一
8.2.2 Hashtable
  • key和value不能为null
  • 同步,单线程,速度慢
  • 和vector集合一样,在1.2版本后被更先进的集合类取代了
  • 其子类Properties集合依然活跃,是一个唯一和IP流结合的集合

9 补充

9.1 JDK9对添加元素的优化

  • list接口、Set接口、Map接口增加了静态方法op(E… element),可以给集合一次性添加多个元素
  • 使用前提
    • 集合中存储的元素个数已经确定、不再改变的时候可以使用
  • 注意
    • of方法只适用于list接口、Set接口、Map接口,不适用于接口的实现类
    • of方法返回值是不能改变的集合,若对集合进行修改(如add,remove),则抛出异常
    • Set接口和Map接口再调用of方法时,不能有重复的元素,否则抛出异常
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值