集合

作者: c_gentle | 来源:发表于2021-01-31 21:28 被阅读0次

一、集合框架体系

集合是Java中提供的一种容器,可以用来存储多个数据,根据不同存储方式形成的体系结构,就叫做集合框架体系。


image.png

每一种容器类底层拥有不同的底层算法。
既然数组可以存储多个数据,为什么要出现集合?
数组的长度是固定的,集合的长度是可变的。
使用Java类封装出一个个容器类,开发者只需要直接调用即可,不用再手动创建容器类。
集合中存储的数据,叫做元素,元素只能是对象(引用类型)。

二、 容器的分类

根据容器的存储特点的不同,可以分成三种情况:


image.png
  • List(列表):允许记录添加顺序,允许元素重复。
  • Set(集合):不记录添加顺序,不允许元素重复。
  • Map(映射):容器中每一个元素都包含一对key和value,key不允许重复,value可以重复。严格上说,并不是容器(集合),是两个容器中元素映射关系。
    注意:List和Set接口继承于Collection接口,Map接口不继承Collection接口


    image.png
  • Collection接口:泛指广义上集合,主要表示List和Set两种存储方式。
  • List接口:表示列表,规定了允许记录添加顺序,允许元素重复的规范。
  • Set接口:表示狭义上集合,规定了不记录添加顺序,不允许元素重复的规范。
  • Map接口:表示映射关系,规定了两个集合映射关系的规范。
    注意:我们使用的容器接口或类都处于java.util包中。

三、List接口

List接口是Collection接口子接口,List接口定义了一种规范,要求该容器允许**记录元素的添加顺序,也允许元素重复。那么List接口的实现类都会遵循这一种规范。
List集合存储特点:

  • 允许元素重复
  • 允许记录元素的添加先后顺序
    该接口常用的实现类有:
  • ArrayList类:数组列表,表示数组结构,采用数组实现,开发中使用对多的实现类,
  • LinkedList类:链表,表示双向列表和双向队列结构,采用链表实现,使用不多。
  • Stack类:栈,表示栈结构,采用数组实现,使用不多。
  • Vector类:向量,其实就是古老的ArrayList,采用数组实现,使用不多。

1、List常用API方法

添加操作
boolean add(Object e):将元素添加到列表的末尾

  • void add(int index, Object element):在列表的指定位置插入指定的元素
  • boolean addAll(Collection c):把c列表中的所有元素添加到当前列表中
    删除操作
    Object remove(int index):从列表中删除指定索引位置的元素,并返回被删除的元素
  • boolean removeAll(Collection c):从此列表中移除c列表中的所有元素
    修改操作
    Object set(int index, Object ele):修改列表中指定索引位置的元素,返回被替换的旧元素
    查询操作
    int size():返回当前列表中元素个数
  • boolean isEmpty():判断当前列表中元素个数是否为0
    Object get(int index):查询列表中指定索引位置对应的元素
  • Object[] toArray():把列表对象转换为Object数组
  • boolean contains(Object o):判断列表是否存在指定对象
    注意,标红的是经常使用的方法。

2、ArrayList类

ArrayList类,基于数组算法的列表,通过查看源代码会发现底层其实就是一个Object数组。
操作List接口常用方法

public class ArrayListDemo1 {
    public static void main(String[] args) {
        //创建一个默认长度的列表对象
        List list = new ArrayList();
        //打印集合中元素的个数
        System.out.println("元素数量:"+list.size());//0
        //添加操作:向列表中添加4个元素
        list.add("Will");
        list.add(100);
        list.add(true);
        list.add("Lucy");
        //查询操作:
        System.out.println("列表中所有元素:"+list);//输出:[Will, 100, true, Lucy]
        System.out.println("元素数量:"+list.size());//4
        System.out.println("第一个元素:"+list.get(0));//Will
        
        //修改操作:把索引为2的元素,替换为wolfcode
        list.set(2, "wolfcode");
        System.out.println("修改后:"+list);//输出:[Will, 100, wolfcode, Lucy]
        
        //删除操作:删除索引为1的元素
        list.remove(1);
        System.out.println("删除后:"+list);//输出:[Will, wolfcode, Lucy]
    }
}

3、LinkedList类

​ ArrayList类,基于数组算法的列表,通过查看源代码会发现底层其实就是一个Object数组。
​ LinkedList类,底层采用链表算法,实现了链表,队列,栈的数据结构。无论是链表还是队列主要操作的都是头和尾的元素,因此在LinkedList类中除了List接口的方法,还有很多操作头尾的方法。

  • void addFirst(Object e) 将指定元素插入此列表的开头。
  • void addLast(Object e) 将指定元素添加到此列表的结尾。
  • Object getFirst() 返回此列表的第一个元素。
  • Object getLast() 返回此列表的最后一个元素。
  • Object removeFirst() 移除并返回此列表的第一个元素。
  • Object removeLast() 移除并返回此列表的最后一个元素。
  • boolean offerFirst(Object e) 在此列表的开头插入指定的元素。
  • boolean offerLast(Object e) 在此列表末尾插入指定的元素。
  • Object peekFirst() 获取但不移除此列表的第一个元素;如果此列表为空,则返回 null。
  • Object peekLast() 获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null。
  • Object pollFirst() 获取并移除此列表的第一个元素;如果此列表为空,则返回 null。
  • Object pollLast() 获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。
  • void push(Object e) 将元素推入此列表所表示的栈。
  • Object pop() 从此列表所表示的栈处弹出一个元素。
  • Object peek() 获取但不移除此列表的头(第一个元素)。
    ​ LinkedList之所以有这么多方法,是因为自身实现了多种数据结构,而不同的数据结构的操作方法名称不同,在开发中LinkedList使用不是很多,知道存储特点就可以了。
public class LinkedListDemo {
    public static void main(String[] args) {
        LinkedList list = new LinkedList();
        //添加元素
        list.addFirst("A");
        list.addFirst("B");
        System.out.println(list);
        list.addFirst("C");
        System.out.println(list);
        list.addLast("D");
        System.out.println(list);
        //获取元素
        System.out.println("获取第一个元素:" + list.getFirst());//C
        System.out.println("获取最后一个元素:" + list.getLast());//D
        //删除元素
        list.removeFirst();
        System.out.println("删除第一个元素后:" + list);//[B, A, D]
        list.removeLast();
        System.out.println("删除最后一个元素后:" + list);//[B, A]
    }
}

4、Stack和Vector类

​ Vector类:基于数组算法实现的列表,其实就是ArrayList类的前身。和ArrayList的区别在于方法使用synchronized修饰,所以相对于ArrayList来说,线程安全,但是效率就低了点。
​ Stack类:表示栈,是Vector类的子类,具有后进先出(LIFO)的特点,拥有push(入栈),pop(出栈)方法。

四、集合元素迭代

1、集合元素遍历

对集合中的每一个元素获取出来。

List<String> list = new ArrayList<>();
list.add("西施");
list.add("王昭君");
list.add("貂蝉");
list.add("杨玉环");

使用for遍历

for (int index = 0; index < list.size(); index++) {
    String ele = list.get(index);
    System.out.println(ele);
}

使用迭代器遍历
Iterator表示迭代器对象,迭代器中拥有一个指针,默认指向第一个元素之前,

  • boolean hasNext():判断指针后是否存在下一个元素
  • Object next():获取指针位置下一个元素,获取后指针向后移动一位
Iterator<String> it = list.iterator();
while(it.hasNext()) {
    String ele = it.next();
    System.out.println(ele);
}

操作原理如下图:


image.png

使用for-each遍历,推荐
语法:

for(元素类型 变量 : 数组/Iterable实例对象){
//TODO
}

这里Iterable实例对象表示,Iterable接口实现类对象,其实就是Collection,不包括Map。

for (String ele : list) {
    System.out.println(ele);
}

2、并发修改异常

需求:在迭代集合时删除集合元素,比如删除王昭君。

List<String> list = new ArrayList<>();
list.add("西施");
list.add("王昭君");
list.add("貂蝉");
list.add("杨玉环");

System.out.println(list);
for (String ele : list) {
    if("王昭君".equals(ele)) {
        list.remove(ele);
    }
}
System.out.println(list);

​ 此时报错java.util.ConcurrentModificationException,并发修改异常。
​ 造成该错误的原因是,不允许在迭代过程中改变集合的长度(不能删除和增加)。如果要在迭代过程中删除元素,就不能使用集合的remove方法,只能使用迭代器的remove方法,此时只能使用迭代器来操作,不能使用foreach。

List<String> list = new ArrayList<>();
list.add("西施");
list.add("王昭君");
list.add("貂蝉");
list.add("杨玉环");
System.out.println(list);
//获取迭代器对象
Iterator<String> it = list.iterator();
while(it.hasNext()) {
    String ele = it.next();
    if("王昭君".equals(ele)) {
        it.remove();
    }
}
System.out.println(list);

五、Set接口

​ Set是Collection子接口,Set接口定义了一种规范,也就是该容器不记录元素的添加顺序,也不允许元素重复,那么Set接口的实现类都遵循这一种规范。
Set集合存储特点:

  • 不允许元素重复
  • 不会记录元素的添加先后顺序
    Set只包含从Collection继承的方法,不过Set无法记住添加的顺序,不允许包含重复的元素。当试图添加两个相同元素进Set集合,添加操作失败,add()方法返回false。
    Set接口定义了一种规范,也就是该容器不记录元素的添加顺序,也不允许元素重复。。
    Set接口常用的实现类有:
  • HashSet类:底层采用哈希表实现,开发中使用对多的实现类,重点。
  • TreeSet类:底层采用红黑树实现,可以对集合中元素排序,使用不多

1、HashSet类

HashSet底层采用哈希表实现,元素对象的hashCode值决定了在哈希表中的存储位置。
​ 当往HashSet集合中添加新的元素对象时,先回判断该对象和集合对象中的hashCode值:

  • 不等: 直接把该新的对象存储到hashCode指定的位置。
  • 相等: 再继续判断新对象和集合对象中的equals做比较。
    • 若equals为true:则视为是同一个对象,则不保存。
    • 若equals为false:存储在之前对象同槽位的链表上,此时操作比较麻烦,不讨论。
      在哈希表中元素对象的hashCode和equals方法的很重要。
      每一个存储到好像表中的对象,都得覆盖hashCode和equals方法用来判断是否是同一个对象,一般的,根据对象的字段数据比较来判断,通常情况下equals为true的时候hashCode也应该相等。
      Eclipse可以根据对象哪些字段做比较而自动生成hashCode和equals方法。
      需求1:操作Set接口常用方法
public class ArrayListDemo2 {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        //添加操作:向列表中添加4个元素
        set.add("Will");
        set.add("wolf");
        set.add("code");
        set.add("Lucy");
        //查询操作:
        System.out.println("集合中所有元素:" + set);//[code, wolf, Will, Lucy]
        System.out.println("元素数量:" + set.size());//4
        System.out.println("是否存在某个元素:" + set.contains("code"));//true
        System.out.println("是否存在某个元素:" + set.contains("code2"));//false
        //删除操作:删除code元素
        set.remove("code");
        System.out.println("删除后:" + set);//[wolf, Will, Lucy]
        //使用for-each遍历
        for (String ele : set) {
            System.out.println(ele);
        }
        //使用迭代器遍历
        Iterator<String> it = set.iterator();
        while (it.hasNext()) {
            Object ele = it.next();
            System.out.println(ele);
        }
    }
}

六、Map接口

1、认识Map

2、Map常用方法

添加操作
boolean put(Object key,Object value):存储一个键值对到Map中

  • boolean putAll(Map m):把m中的所有键值对添加到当前Map中
    删除操作
    Object remove(Object key):从Map中删除指定key的键值对,并返回被删除key对应的value
    修改操作
  • 无专门的方法,可以调用put方法,存储相同key,不同value的键值对,可以覆盖原来的。
    查询操作
  • int size():返回当前Map中键值对个数
  • boolean isEmpty():判断当前Map中键值对个数是否为0.
    Object get(Object key):返回Map中指定key对应的value值,如果不存在该key,返回null
  • boolean containsKey(Object key):判断Map中是否包含指定key
  • boolean containsValue(Object value):判断Map中是否包含指定value
    Set keySet():返回Map中所有key所组成的Set集合
    Collection values():返回Map中所有value所组成的Collection集合
  • Set<Entry> entrySet():返回Map中所有键值对所组成的Set集合
    注意,标红的是重度使用的方法。

3、HashMap

HashMap底层基于哈希表算法,Map中存储的key对象的hashCode值决定了在哈希表中的存储位置,因为Map中的key是Set,所以不能保证添加的先后顺序,也不允许重复。

需求1:操作Map接口常用方法

public class HashMapDemo1{
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("girl1", "西施");
        map.put("girl2", "王昭君");
        map.put("girl3", "貂蝉");
        map.put("girl4", "杨玉环");
        System.out.println("map中有多少键值对:"+map.size());
        System.out.println(map);
        System.out.println("是否包含key为girl1:"+map.containsKey("girl1"));
        System.out.println("是否包含value为貂蝉:"+map.containsValue("貂蝉"));
        //替换key为girl3的value值
        map.put("girl3", "小乔");
        System.out.println(map);
        //删除key为girl3的键值对
        map.remove("girl3");
        System.out.println(map);
    }
}

Map的迭代遍历:

//获取Map中所有的key
Set<String> keys = map.keySet();
System.out.println("Map中所有key:"+keys);
//获取Map中所有的value
Collection<String> values = map.values();
System.out.println("Map中所有value:"+values);
//获取Map中所有的key-value(键值对)
Set<Entry<String, String>> entrys = map.entrySet();
for (Entry<String, String> entry : entrys) {
    String key = entry.getKey();
    String value = entry.getValue();
    System.out.println(key+"->"+value);
}

相关文章

  • 我的Swift的学习总结 -->第二周

    集合 集合:Set,定义一个集合可以写成:var 集合名 : Set<集合类型> = [集合元素],具体的集合应用...

  • markdown 测试

    集合 集合 集合 引用

  • kotlin学习第五天:集合,高阶函数,Lambda表达式

    集合 list集合 list集合分为可变集合与不可变集合。由list of创建的集合为不可变集合,不能扩容,不能修...

  • kotlin练习 ---- 集合练习

    kotlin练习 - 集合练习 Set集合 Set集合创建 Set集合的使用 List集合 List集合创建 Li...

  • 集合总结

    集合 集合分为单列集合和双列集合两种: 一.单列集合: Collection是单列集合的顶级接口: 其中有三类集合...

  • 映射、元组、集合

    映射 元组 集合 集合之seq 集合之set 集合之map

  • 16.Collection集合

    主要内容: Collection 集合 迭代器 增强for List 集合 Set 集合 1,集合 集合是java...

  • 集合与有序集合

    集合分为有序集合 (zset) 和无序集合 (set), 一般无序集合也直接说成集合 无序集合 (set) 无序集...

  • python入坑第八天|集合

    好的,各位蛇友,我们今天来学习集合。 内容: 集合的创建 集合操作符号 集合的内置函数 集合的创建 集合用set(...

  • 集合框架

    集合框架的概念 集合:存放数据的容器 集合框架:java中,用于表示集合,以及操作集合的类和接口的统称 数组与集合...

网友评论

      本文标题:集合

      本文链接:https://www.haomeiwen.com/subject/idkrtltx.html