Java集合进阶

Java集合进阶

集合体系结构

单列集合(Collection)

在添加数据的时候,每次只能添加一个元素。

1720264515634

双列集合(Map)

特点
  • 双列集合一次需要存一对数据,分别为键和值
  • 键不能重复,值可以重复
  • 键和值是一一对应的,每一个键只能找到自己对应的值
  • 键和值这个整体,我们称之为“键值对”或者“键值对象”,在Java中叫做“Entry对象”

1720678700090

Map的常见API

Map是双列集合的顶层接口,他的功能是全部双列集合都可以继承使用

在这里插入图片描述

1720500659217

Map的遍历方式

键找值

public class MapDemo2{
	public static void main(String[] args){
		Map<String,String> map = new HashMap<>();
		map.put("嘻嘻","呼呼");
		map.put("哈哈","嘿嘿");
		map.put("芜湖","嗯哼");
		
		Set<String> keys = map.keySet();
		for(String key:keys){
			String value = map.get(key);
			System.out.println(key + "=" + value); 
		}
	}
}

键值对

package com.example.demo;

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

public class Text {
    public static void main(String[] args) {
        //1.创建Map集合的对象
        Map<String,String> map = new HashMap<>();
        //2.添加元素
        map.put("花园宝宝1","玛卡巴卡");
        map.put("花园宝宝2","唔西迪西");
        map.put("花园宝宝3","汤伯利伯");

        //3.Map集合的第二种遍历方式
        //通过键值对对象进行遍历
        //3.1通过一个方法获取所有的键值对对象,返回一个Set集合
        Set<Map.Entry<String, String>> entries = map.entrySet();
        //3.2 遍历entries这个集合去得到里面的每个键值对对象
        for (Map.Entry<String,String> entry:entries){
//            3.3利用Entry调用get方法用来获取每一个键和每一个值
            String key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + "=" + value);
        }

    }
}

Lambda表达式

package com.example.demo;

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

public class Text {
    public static void main(String[] args) {
        //1.创建Map集合的对象
        Map<String,String> map = new HashMap<>();
        //2.添加元素
        map.put("花园宝宝1","玛卡巴卡");
        map.put("花园宝宝2","唔西迪西");
        map.put("花园宝宝3","汤伯利伯");

        //3.利用Lambda表达式进行遍历
        //底层:
        //forEach其实就是利用第二种方式进行遍历,依次得到每一个键和值
        //再调用accept方法
        map.forEach((key, value)->  System.out.println(key + "=" + value));

    }
}
HashMap的特点
  1. HashMap是Map里面的一个实现类

  2. 特点都是由键决定的:无序、不重复、无索引

  3. HashMap跟HashSet底层原理是一模一样的,都是哈希表结构

    HashMap底层是哈希表结构的

    依赖hashCode方法和equals方法保证键的唯一

    如果键存储的是自定义对象,需要重写hashCode和equals方法。如果值存储自定义对象,不需要重写hashCode和equals方法。

1720769338142

1720770352163

1720769545905

1720769652524

1720769838663

1720769994018

1720770051090

++modCount:跟并发修改异常有关

1720770120210

1720772489887

1720772557069

1720773161506

LinkedHashMap的特点

由键决定有序、不重复、无索引

有序:保证存取的元素顺序一致

原理:底层数据结构依然是哈希表,只是每个键值对元素又额外的多了一个双链表的机制记录存储的顺序

TreeMap的特点

TreeMap跟TreeSet底层原理一样,都是红黑树结构的

由键决定特性:不重复、无索引、可排序

可排序:对键进行排序

注意:默认按照键的从小到大进行排序,也可以自己规定键的排序规则

代码书写两种排序规则

  • 实现Comparable接口,指定比较规则
  • 创建集合时传递Comparator比较器对象,指定比较规则

在这里插入图片描述

1720773726115

1720773785904

1720773954440

1720774310392

1720774408662

1720774538843

1720774598707

在这里插入图片描述

1720775104557

1720775435686

1720775469530

可变参数

本质上是一个数组

1720775735679

小细节:

  • 在方法的形参中最多只能写一个可变参数
  • 在方法当中,如果除了可变参数以外,还有其他的形参,那么可变参数要写在最后

Collections

  • java.util.Collections:是集合工具类
  • 作用:Collections不是集合,而是集合的工具类

常用的API

方法名称说明
public static boolean addAll(Collection c,T…elements)批量添加元素
public static void shuffle(List<?> list)打乱List集合元素的顺序

不可变集合

不能被修改的集合

应用场景

  • 如果某个数据不能被修改,把它防御性地拷贝到不可变集合中是个很好的实践。
  • 当集合对象被不可信的库调用时,不可变形式是安全的。
  • 简单理解:不想让别个修改集合中的内容

书写格式

方法名称说明
static List of(E…elements)创建一个具有指定元素的List集合对象
static Set of(E…elements)创建一个具有指定元素的Set集合对象(创建时要确保元素的唯一性)
static<K,V> Map<K,V> of(E…elements)创建一个具有指定元素的Map集合对象(创建时键是不能重复的,Map里面的of方法参数有上限,最多只能传递20个参数。)

注意:这个集合不能添加,不能删除,不能修改。

Collection集合

1720264659273

1720264875594

1720264838053

1720264933275

1720265254283

Collection的遍历方式

迭代器遍历
迭代器

在Java中的类时Iterator,迭代器是集合专用的遍历方式。

特点:

不依赖索引

1720265624748

1720266677633

增强for遍历
  • 增强for的底层就是迭代器,为了简化迭代器的代码书写的。

  • 它是JDK5之后出现的,其内部原理就是一个Iterator迭代器。

  • 所有的单列集合和数组才能用增强for进行遍历。

    for(元素的数据类型 变量名 : 数组或者集合){
    }
    
细节:
  • 修改增强for中的变量,不会改变集合中原本的数据
Lambda表达式遍历
  • 得益于JDK8开始的新技术Lambda表达式,提供了一种更简单、更直接的遍历集合的方式
方法名称说明
default void forEach(Consumer<? super T> action):结合Lambda遍历集合
package com.example.demo;

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

public class Text {
    public static void main(String[] args) {
        Collection<String> coll  = new ArrayList<>();
        coll.add("aaa");
        coll.add("aaa");
        coll.add("aaa");
        coll.add("aaa");

//        底层原理:其实也会自己遍历,
//        依次得到每一个元素。把得到的每一个元素,传递给下面accept方法
        //s表示集合中的每一个数据
        coll.forEach( s -> System.out.println(s));
    }
}

1720268366298

List集合

1720268446701

1720268507375

  • 在调用remove方法的时候,如果方法出现重载现象:优先调用,实参跟形参类型一致的那个方法。
  • 调用set方法修改制定索引上的元素,会把被修改的元素进行返回。

List集合的遍历方式

迭代器遍历
package com.example.demo;

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

public class Text {
    public static void main(String[] args) {

//        利用多态的方式创建集合对象并添加元素
        List<String> list = new ArrayList<>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        list.add("ddd");

//      迭代器遍历
        Iterator<String> it = list.iterator();
        while (it.hasNext()){
            String str = it.next();
            System.out.println(str);
        }

    }
}
迭代器底层原理

1720316064457

列表迭代器遍历
package com.example.demo;

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

public class Text {
    public static void main(String[] args) {

//        利用多态的方式创建集合对象并添加元素
        List<String> list = new ArrayList<>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        list.add("ddd");

//      列表迭代器
//        额外增加了一个方法:在遍历过程中,可以添加元素
        ListIterator<String> it = list.listIterator();
        while (it.hasNext()){
            String str = it.next();
            if("bbb".equals(str)){
                it.add("qqq");
            }
        }
        System.out.println(list);
    }
}
增强for遍历
package com.example.demo;

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

public class Text {
    public static void main(String[] args) {

//        利用多态的方式创建集合对象并添加元素
        List<String> list = new ArrayList<>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        list.add("ddd");

//      增强for遍历
//        s就是一个第三方的变量
//        在循环的过程中,依次表示集合中的每一个元素
        for (String s : list) {
            System.out.println(s);
        }

    }
}
Lambda表达式遍历
package com.example.demo;

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

public class Text {
    public static void main(String[] args) {

//        利用多态的方式创建集合对象并添加元素
        List<String> list = new ArrayList<>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        list.add("ddd");

//      Lambda表示式遍历
//        forEach方法的底层其实就是一个循环遍历,依次得到集合中的每一个元素
//        并把每一个元素传递给下面的accept方法
//        accept方法的形参s,依次表示集合中的每一个元素
        list.forEach( s-> System.out.println(s));

    }
}
普通for循环(因为List集合存在索引)
package com.example.demo;

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

public class Text {
    public static void main(String[] args) {

//        利用多态的方式创建集合对象并添加元素
        List<String> list = new ArrayList<>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        list.add("ddd");

//      普通for循环进行遍历
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
    }
}

1720270761435

数据结构

  • 计算机存储、组织数据的方式。
  • 数据相互之间是以什么方式排列在一起的。
  • 为了更加方便的管理和使用数据,需要结合具体业务场景进行选择。
  • 一般情况下,精心选择的数据结构可以带来更高的运行或者存储效率。

1720271083089

1720271484269

队列

1720271582166

数组

1720271949269

链表

1720271999463

添加一个元素

1720272266694

删除一个元素

1720272317765

1720272442001

1720327506219

1720327549634

1720327700646

1720327809730

1720327919249

1720328001125

1720328254086

1720328287356

从小到大的顺序进行排列的

1720328336934

1720328364432

1720328752008

1720331503013

1720331483600

1720331593527

1720331664406

1720331986904

1720333525695

1720333887194

1720334689780

ArrayList集合

底层原理

1720273040390

1720273858854

1720274202831

LinkedList集合

1720275864736

1720276143308

1720315062161

泛型

1720316421229

1720316734923

1720317003332

1720317122363

泛型类

1720317375940

泛型方法

1720324496957

//格式:
修饰符<类型> 返回值类型 方法名(类型 变量名){

}
//举例:
public <T> void show(T t){
    //调用该方法时,T就确定类型
}
//此处T可以理解为变量,但是不是用来记录数据的,而是记录类型的,可以写成:T E K V等

泛型接口

//格式
修饰符 interface 接口名<类型>{

}
//举例
public interface List<E>{

}
使用方式
  • 实现类给出具体类型
  • 实现类延续泛型,创建对象时在确定

泛型的继承和通配符

泛型不具备继承性,但是数据具备继承性

1720327163550

1720327296527

Set系列集合

  • 无序:存取的顺序不一致
  • 不重复:可以去除重复
  • 无索引:没有带索引的方法,所以不能使用普通for循环遍历,也不能通过索引来获取元素

Set接口中的方法基本与Collection的API一致。

Set集合的实现类

HashSet:无序、不重复、无索引
底层原理
  • HashSet集合底层采取哈希表存储数据

  • 哈希表是一种对于增删改查数据性能都较好的结构

    哈比表组成

    ​ 1.JDK8之前:数组+链表

    ​ 2.JDK8之后:数组+链表+红黑树

    哈希值:对象的整数表现形式

    ​ 1.根据hashCode方法算出来的int类型的整数

    ​ 2.该方法定义在Object类中,所有对象都可以调用,默认使用地址值进行计算

    ​ 3.一般情况下,会重写hashCode方法,利用对象内部的属性值计算哈希值

    对象的哈希值特点

    ​ 1.如果没有重写hashCode方法,不同对象计算出的哈希值是不同的

    ​ 2.如果已经重写hashCode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的

    ​ 3.在小部分情况下,不同的属性值或者不同的地址值计算出的哈希值也有可能一样(哈希碰撞)

1720340786117

JDK8以后,当链表长度超过8,而且数组长度大于等于64时,自动转换为红黑树

当集合中存储的是自定义对象,必须重写hashCode和equals方法

LinkedHashSet:有序、不重复、无索引
底层原理

这里的有序指的是保证存取元素的顺序一致

原理:底层数据结构依然是哈希表,只是每个元素又额外的多了一个双链表的机制记录存储的顺序

1720341799391

TreeSet:可排序、不重复、无索引
特点:
  • 不重复、无索引、可排序
  • 可排序:按照元素的默认规则(有大有小)排序
  • TreeSet集合底层是基于红黑树的数据结构实现排序的,增删改查性能都较好。
TreeSet集合默认的规则

对于数值类型:Integer,Double,默认按照从小到大的顺序进行排序

对于字符、字符串类型:按照字符在ASCII码表中的数字升序进行排序

TreeSet的两种比较方式

方式一:

默认排序/自然排序:JavaBean类实现Comparable接口制定比较规则

方式二:

比较器排序:创建TreeSet对象的时候,传递比较器Comparable制定规则

使用原则:默认使用第一种没如果第一种不能满足当前需求,就使用第二种。

方法返回值的特点:

负数:表示当前要添加的元素是小的,存左边

正数:表示当前要添加的元素是大的,存右边

0:表示当前要添加的元素已经存在,舍弃

使用场景

如果想要集合中的元素可重复

  • 用ArrayList集合,基于数组的。(用的最多)

如果想要集合中的元素可重复,而且当前的增删操作明显多于查询

  • 用的LinkedList集合,基于链表的。

如果想对集合中的元素去重

  • 用HashSet集合,基于哈希表。(用的最多)

如果想对集合中的元素去重,而且保证存取顺序

  • 用LinkedHashSet集合,基于哈希表和双链表,效率低于HashSet

如果想对集合中的元素进行排序

Set:可排序、不重复、无索引

特点:
  • 不重复、无索引、可排序
  • 可排序:按照元素的默认规则(有大有小)排序
  • TreeSet集合底层是基于红黑树的数据结构实现排序的,增删改查性能都较好。
TreeSet集合默认的规则

对于数值类型:Integer,Double,默认按照从小到大的顺序进行排序

对于字符、字符串类型:按照字符在ASCII码表中的数字升序进行排序

TreeSet的两种比较方式

方式一:

默认排序/自然排序:JavaBean类实现Comparable接口制定比较规则

方式二:

比较器排序:创建TreeSet对象的时候,传递比较器Comparable制定规则

使用原则:默认使用第一种没如果第一种不能满足当前需求,就使用第二种。

方法返回值的特点:

负数:表示当前要添加的元素是小的,存左边

正数:表示当前要添加的元素是大的,存右边

0:表示当前要添加的元素已经存在,舍弃

使用场景

如果想要集合中的元素可重复

  • 用ArrayList集合,基于数组的。(用的最多)

如果想要集合中的元素可重复,而且当前的增删操作明显多于查询

  • 用的LinkedList集合,基于链表的。

如果想对集合中的元素去重

  • 用HashSet集合,基于哈希表。(用的最多)

如果想对集合中的元素去重,而且保证存取顺序

  • 用LinkedHashSet集合,基于哈希表和双链表,效率低于HashSet

如果想对集合中的元素进行排序

用TreeSet集合,基于红黑树。后续也可以用List集合实现排序

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值