java学习之容器集合


一、Collection集合

1.1集合体系结构

集合类的特点

提供一种存储空间可变的存储模型,存储的数据容量可以随时发生改变

1.2Collection集合概述和基本使用

Collection集合概述

是单列集合的顶层接口,它表示一组对象,这些对象也称为Collection的元素

JDK 不提供此接口的任何直接实现,它提供更具体的子接口(如Set和List)实现

1.3Collection集合的常用方法

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

1.4Collection集合的遍历

迭代器的介绍

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

Iterator iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到

迭代器是通过集合的iterator()方法得到的,所以我们说它是依赖于集合而存在的

二、List集合

2.1List集合概述和特点

List集合概述

有序集合(也称为序列),用户可以精确控制列表中每个元素的插入位置。用户可以通过整数索引访问元素,并搜索列表中的元素

与Set集合不同,列表通常允许重复的元素

List集合特点

有索引

可以存储重复元素

元素存取有序

2.2List集合的特有方法

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

2.3并发修改异常

出现的原因

迭代器遍历的过程中,通过集合对象修改了集合中的元素,造成了迭代器获取元素中判断预期修改值和实际修改值不一致,则会出现:ConcurrentModificationException

解决的方案

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

2.4列表迭代器

ListIterator介绍

通过List集合的listIterator()方法得到,所以说它是List集合特有的迭代器

用于允许程序沿任一方向遍历的列表迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置

2.5增强for循环

格式

for(元素数据类型 变量名 : 数组/集合对象名) {
    循环体;
}

举例说明

int[] arr = {1,2,3,4,5};
for(int i : arr) {
    System.out.println(i);
}

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

三、数据结构

3.1栈和队列

一端开口(栈顶),一段封闭(栈底)
数据进入栈模型的过程被称为:压栈或进栈
数据离开栈模型的过程被称为:弹栈或出栈
先进后出的模型

队列

两端都是开口的,一端叫前端,一端叫后端
数据从后端进入队列模型的过程被称为:入队列
数据从前端离开队列模型的过程被称为:出队列
先进先出的模型

3.2数组和链表

数组

查询数据通过索引定位,查询任意数据耗时相同,查询效率高
删除数据时,要将原始数据删除,同时后面的每个数据前移,删除效率低
添加数据时,添加位置后的每个数据需要后移,再添加元素,添加效率极低
总结:查询快、增删慢

链表

结点:前面存储具体的数据,后面存储下一个结点的地址
对比数组来说,查询慢,增删快

四、List集合的实现类

4.1List集合子类的特点

常用子类
ArrayList
底层是数组结构实现,查询快、增删慢
LinkedList
底层是链表结构实现,查询慢、增删快

4.2LinkedList集合的特有功能

方法名说明
public void addFirst(E e)在该列表开头插入指定的元素
public void addLast(E e)将指定的元素追加到此列表的末尾
public E getFirst()返回此列表中的第一个元素
public E getLast()返回此列表中的最后一个元素
public E removeFirst()从此列表中删除并返回第一个元素
public E removeLast()从此列表中删除并返回最后一个元素

五、Set集合

5.1Set集合概述和特点

Set集合的特点:

元素存取无序

没有索引、只能通过迭代器或增强for循环遍历

不能存储重复元素

5.2哈希值

哈希值简介:

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

如何获取哈希值?

Object类中的public int hashCode():返回对象的哈希码值

哈希值的特点

同一个对象多次调用hashCode()方法返回的哈希值是相同的。

默认情况下,不同对象的哈希值是不同的。而重写hashCode()方法,可以实现让不同对象的哈希值相同

5.3HashSet集合概述和特点

HashSet集合的特点

底层数据结构是哈希表

对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致

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

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

5.4HashSet集合保证元素唯一性源码分析

HashSet集合保证元素唯一性的原理

​ 1.根据对象的哈希值计算存储位置

​ 如果当前位置没有元素则直接存入

​ 如果当前位置有元素存在,则进入第二步

​ 2.当前元素的元素和已经存在的元素比较哈希值

​ 如果哈希值不同,则将当前元素进行存储

​ 如果哈希值相同,则进入第三步

​ 3.通过equals()方法比较两个元素的内容

​ 如果内容不相同,则将当前元素进行存储

​ 如果内容相同,则不存储当前元素

5.5LinkedHashSet集合概述和特点

LinkedHashSet集合特点:

哈希表和链表实现的Set接口,具有可预测的迭代次序

由链表保证元素有序,也就是说元素的存储和取出顺序是一致的

由哈希表保证元素唯一,也就是说没有重复的元素

六、Set集合排序

6.1TreeSet集合概述和特点

TreeSet集合概述

元素有序,可以按照一定的规则进行排序,具体排序方式取决于构造方法

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

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

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

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

6.2自然排序Comparable的使用

案例需求

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

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

实现步骤

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

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

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

6.3比较器排序Comparator的使用

案例需求

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

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

实现步骤

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

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

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

七、泛型

7.1泛型概述和好处

泛型概述

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

​ 它的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,然后在使用/调用时传入具体的类型。这种参数类型可以用在类、方法和接口中,分别被称为泛型类、泛型方法、泛型接口

泛型定义格式

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

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

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

泛型的好处

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

避免了强制类型转换

7.2泛型类

定义格式

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

示例代码

泛型类

public class Generic<T> {
    private T t;

    public T getT() {
        return t;
    }

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

7.3泛型方法

定义格式

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

示例代码

带有泛型方法的类

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

7.4泛型接口

定义格式

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

示例代码

泛型接口

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);
    }
}

7.5类型通配符

类型通配符的作用

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

类型通配符的分类

类型通配符:<?>

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

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

类型通配符上限:<? extends 类型>

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

类型通配符下限:<? super 类型>

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

八、可变参数

8.1可变参数介绍

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

8.2可变参数定义格式

修饰符 返回值类型 方法名(数据类型… 变量名) { }

8.3可变参数的注意事项

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

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

8.4可变参数的使用

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

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

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

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

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

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

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

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

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

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

九、Map集合

9.1Map集合概述和特点

Map集合概述

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

Map集合的特点

键值对映射关系

一个键对应一个值

键不能重复,值可以重复

元素存取无序

9.2Map集合的基本功能

方法介绍

方法名说明
V put(K key,V value)添加元素
V remove(Object key)根据键删除键值对元素
void clear()移除所有的键值对元素
boolean containsKey(Object key)判断集合是否包含指定的键
boolean containsValue(Object value)判断集合是否包含指定的值
boolean isEmpty()判断集合是否为空
int size()集合的长度,也就是集合中键值对的个数

9.3Map集合的获取功能

方法介绍

方法名说明
V get(Object key)根据键获取值
Set keySet()获取所有键的集合
Collection values()获取所有值的集合
Set<Map.Entry<K,V>> entrySet()获取所有键值对对象的集合

9.4Map集合的遍历

方式1

遍历思路

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

把所有的丈夫给集中起来

遍历丈夫的集合,获取到每一个丈夫

根据丈夫去找对应的妻子

步骤分析

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

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

根据键去找值。用get(Object key)方法实现

方式2

遍历思路

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

获取所有结婚证的集合

遍历结婚证的集合,得到每一个结婚证

根据结婚证获取丈夫和妻子

步骤分析

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

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

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

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

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

用getKey()得到键

用getValue()得到值

十、Collections集合工具类

10.1Collections概述和使用

Collections类的作用

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

Collections类常用方法

方法名说明
public static void sort(List list)将指定的列表按升序排序
public static void reverse(List<?> list)反转指定列表中元素的顺序
public static void shuffle(List<?> list)使用默认的随机源随机排列指定的列表

10.2斗地主案例

案例需求

​ 通过程序实现斗地主过程中的洗牌,发牌和看牌。要求:对牌进行排序

代码实现

public class PokerDemo {
public static void main(String[] args) {
    //创建HashMap,键是编号,值是牌
    HashMap<Integer, String> hm = new HashMap<Integer, String>();

    //创建ArrayList,存储编号
    ArrayList<Integer> array = new ArrayList<Integer>();

    //创建花色数组和点数数组
    String[] colors = {"♦", "♣", "♥", "♠"};
    String[] numbers = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};

    //从0开始往HashMap里面存储编号,并存储对应的牌。同时往ArrayList里面存储编号
    int index = 0;

    for (String number : numbers) {
        for (String color : colors) {
            hm.put(index, color + number);
            array.add(index);
            index++;
        }
    }
    hm.put(index, "小王");
    array.add(index);
    index++;
    hm.put(index, "大王");
    array.add(index);

    //洗牌(洗的是编号),用Collections的shuffle()方法实现
    Collections.shuffle(array);

    //发牌(发的也是编号,为了保证编号是排序的,创建TreeSet集合接收)
    TreeSet<Integer> lqxSet = new TreeSet<Integer>();
    TreeSet<Integer> lySet = new TreeSet<Integer>();
    TreeSet<Integer> fqySet = new TreeSet<Integer>();
    TreeSet<Integer> dpSet = new TreeSet<Integer>();

    for (int i = 0; i < array.size(); i++) {
        int x = array.get(i);
        if (i >= array.size() - 3) {
            dpSet.add(x);
        } else if (i % 3 == 0) {
            lqxSet.add(x);
        } else if (i % 3 == 1) {
            lySet.add(x);
        } else if (i % 3 == 2) {
            fqySet.add(x);
        }
    }

    //调用看牌方法
    lookPoker("林青霞", lqxSet, hm);
    lookPoker("柳岩", lySet, hm);
    lookPoker("风清扬", fqySet, hm);
    lookPoker("底牌", dpSet, hm);
}

//定义方法看牌(遍历TreeSet集合,获取编号,到HashMap集合找对应的牌)
public static void lookPoker(String name, TreeSet<Integer> ts, HashMap<Integer, String> hm) {
    System.out.print(name + "的牌是:");
    for (Integer key : ts) {
        String poker = hm.get(key);
        System.out.print(poker + " ");
    }
    System.out.println();
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值