Java数据结构及工具类

本文详细介绍了Java中的数据结构,如栈、队列、数组、链表和红黑树,以及List接口及其子类ArrayList和LinkedList。讲解了Set接口中的HashSet和LinkedHashSet,包括它们的存储结构和元素唯一性的实现。此外,还涵盖了Map接口及其子类HashMap和LinkedHashMap,以及Collections工具类和自定义比较器。文章最后提到了JDK9对集合添加的优化和Debug追踪与调试的基础知识。
摘要由CSDN通过智能技术生成

`1 数据结构

常见的数据结构 : 栈堆 , 队列, 数组, 链表和红黑树

栈 : 它是运算受限的线性表, 其限制是仅允许在标的一端进行插入和删除操作, 不允许在其他任何位置进行添加, 查找, 删除等操作

  • 先进后出(即,存进去的元素,要在后它后面的元素依次取出后,才能取出该元素)
  • 栈的入口, 出口都是栈的顶端位置

压栈 : 就是存元素。即,把元素存储到栈的顶端位置,栈中已有元素依次向栈底方向移动一个位置

弹栈 : 就是取元素。即,把栈的顶端位置元素取出,栈中已有元素依次向栈顶方向移动一个位置。

队列

队列 : 它也是运算受限的线性表, 其限制是仅允许在表的一端进行插入,而在表的另一端进行删除。

  • 先进先出 (即,存进去的元素,要在后它前面的元素依次取出后,才能取出该元素)

数组

数组 : 它是有序的元素序列, 数组是在内存中开辟一段连续的空间, 并在此空间存放元素; 每个元素都有对应的索引

特点 : 查找快, 通过索引, 可以快速访问指定位置的元素; 但是插入和删除操作费时

  • 指定索引位置增加元素 : 需要创建一个新数组,将指定新元素存储在指定索引位置,再把原数组元素根据索引,复制到新数组对应索引的位置
  • 指定索引位置删除元素 : 需要创建一个新数组,把原数组元素根据索引,复制到新数组对应索引的位置,原数组中指定索引位置元素不复制到新数组中

链表

链表 : linked list 是由一系列节点node(链表中每一个元素称为节点)组成, 节点可以在运行时动态生成, 每个节点包括两个部分: 一个是存储数据元素的数据域, 另外一个是存储指向下一个节点地址的指针域, 常见的链表还有单向链表和双向链表

特点 : 多个节点之间, 通过地址链接; 例如,多个人手拉手,每个人使用自己的右手拉住下个人的左手,依次类推,这样多个人就连在一起了

存储元素和取出元素的顺序有可能不一样

  • 查找元素慢 : 想查找某个元素, 需要通过链接的节点, 依次向后查找指定元素
  • 增删元素快 : 只需要修改链接下个元素的地址即可

红黑树

二叉树 : binary tree, 是每个节点不超过 2 的有序树; 就是一种类似于我们生活中树的结构, 只不过每个节点上都最多只能有两个子节点; 二叉树是每个节点最多有两个子树的树结构; 顶上的叫根节点, 两把被称为" 左子树"和" 右子树"

红黑树 : 本身就是一颗二叉查找数 , 将节点插入后, 该数仍然是一颗二叉查找数, 也就意味着, 树的键值仍然是有序的

红黑树的约束 :

  1. 节点可以是红色或者黑色的
  2. 根节点是黑色的
  3. 叶子节点(特指空节点)是黑色的
  4. 每个红色节点的子节点是黑色的
  5. 任何一个节点到每一个叶子节点的所有路径上黑色节点数相同

特点 : 速度特别快, 趋近平衡树, 查找叶子元素最少和最多次数不多于二倍

2 List接口

以下 接口 都是 Collection接口中的子类

java.util.List 接口继承自Collection 接口, 是单列集合的一个重要分支 , 习惯性地会将实现了List接口的对象称为List集合, 在List集合中允许出现重复的元素, 所有的元素是以一种线性方式进行存储的, 在程序中可以通过索引来访问集合中的指定元素; List集合还有一个特点就是元素有序, 即元素的存入顺序和取出顺序一致

特点:

  1. 它是一个元素存取有序的集合。例如,存元素的顺序是11、22、33。那么集合中,元素的存储就是按照11、22、33的顺序完成的
  2. 它是一个带有索引的集合, 通过索引就可以精确的操作集合中的元素(与数组的索引是一个道理)
  3. 集合中可以有重复的元素, 铜鼓哦元素的equals方法,来比较是否为重复的元素

List接口中常用方法

List 作为Collection集合 的子接口, 不但继承了 Collection 接口中的全部方法, 而且还增加了一些根据元素索引来操作集合的特有方法

public void add(int index,E element) : 将指定的元素, 添加到该集合中的指定位置上

public E get(int index) : 返回集合中指定位置的元素

public E remove(int index) : 移除列表中指定位置的元素 , 返回的是被移除的元素

public E set(int index , E element) : 用指定元素替换集合中指定位置的元素, 返回值是更新前的元素

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

public class Demo01List {
   

	public static void main(String[] args) {
   
		// 创建一个List集合对象, 多态
		List<String> list = new ArrayList<>();

		// 不加索引, 默认在list尾端加入
		list.add("a");
		list.add("b");
		list.add(1,"itcast");
		list.add("d");
		list.add("e");
		System.out.println(list);

		// 获取指定索引的元素
		System.out.println(list.get(1));
		
		// 移除指定索引的元素
		System.out.println(list.remove(2));

		// 更新指定索引的元素
		list.set(1,"HelloWorld");
		System.out.println(list);
	}
}

3 List的子类

ArrayList集合

java.util.ArrayList 集合数据存储的结构是数组结构; 元素增删慢, 查找快, 由于日常开发中使用最多的功能为查询数据, 遍历数据; 所以ArrayList 是常用的集合

LinkedList集合

java.util.LinkedList 集合数据存储的结构是链表结构, 方便元素添加, 删除的集合

LinkedList 是一个双向链表, 那么双向链表是什么样子的呢?

实际开发对一个集合元素的添加与删除经常涉及到首尾操作, LinkedList提供大量的首尾操作的方法

  • public void addFirst(E e) : 将指定元素插入到此列表的开头
  • public void addLast(E e) : 将指定元素插入到此列表的结尾
  • public void getFirst() : 获取此列表的第一个元素
  • public void getLast() : 获取此列表的最后一个元素
  • public void removeFirst() : 移除并返回此列表的第一个元素
  • public void removeLast() : 移除并返回此列表的最后一个元素
  • public E pop() : 从此列表中所表示的栈出弹出栈顶的一个元素
  • public E push() : 将元素推入到此列表所表示的栈
  • public boolean isEmpty() : 如果列表不包含元素, 则返回true

LinkedList 是 List的子类, List中的方法LinkedList都是可以使用的

	public static void main(String[] args) {
   
		LinkedList<String> link = new LinkedList<String>();
		//添加元素
		link.addFirst("abc1");
		link.addFirst("abc2");
		link.addFirst("abc3");
		link.addFirst("abc4");
		System.out.println(link);
		// 获取元素
		System.out.println(link.getFirst());
		System.out.println(link.getLast());
		// 删除元素
		System.out.println(link.removeFirst());
		System.out.println(link.removeLast());

		System.out.println(link);
		while (!link.isEmpty()) {
    //判断集合是否为空
			System.out.println(link.pop()); //弹出集合中的栈顶元素
		}
		System.out.println(link);
	}	public static void main(String[] args) {
   
		LinkedList<String> link = new LinkedList<String>();
		//添加元素
		link.addFirst("abc1");
		link.addFirst("abc2");
		link.addFirst("abc3");
		link.addFirst("abc4");
		System.out.println(link);
		// 获取元素
		System.out.println(link.getFirst());
		System.out.println(link.getLast());
		// 删除元素
		System.out.println(link.removeFirst());
		System.out.println(link.removeLast());

		System.out.println(link);
		while (!link.isEmpty()) {
    //判断集合是否为空
			System.out.println(link.pop()); //弹出集合中的栈顶元素
		}
		System.out.println(link);
	}

4 Set接口

java.util.Set 接口和 javautil.List 接口一样, 同样继承自 Collection接口, 它与Cllevtion接口中的方法基本一致, 并没有对Collection接口进行功能上的扩充, 只是比 Collection 接口国家严格了, 与List 接口的不同是, Set 接口中元素无序, 并且都会以某种规则保证存入的元素不会出现重复

Set 集合有多个子类, 这里介绍java.util.HashSet, java.util.LinkedHashSer

Set集合取出元素的方式可以采用 : 迭代器, 增强for

HashSet集合

java.util.HashSetSet接口的一个实现类,它所存储的元素是不可重复的,并且元素都是无序的(即存取顺序不一致)。java.util.HashSet底层的实现其实是一个java.util.HashMap , 查询的速度非常快

HashSet 是根据对象的哈希值来确定元素在集合中存储的位置, 因此具有良好的存取和查找性能, 保证元素唯一性的方式依赖于 : hashCodeequals 方法

HashSet集合存储数据的结构(哈希表)

在JDK1.8之前, 哈希表底层此案有数组+链表实现, 即使用链表处理冲突, 同一hash值的链表都存储在一个链表里; 但是当位于一个桶中的元素较多, 即has值相等的元素较多时, 通过key值一次查找的效率降低; 在JDK1.8中, 哈希表采用数组+链表+红黑树实现, 当链表长度超过阈值( 8 )时,将链表转换为红黑树

总而言之, JDK1.8引入红黑树大程度优化了HashMap的性能, 那么对于我们来讲保证HashSet 集合元素的唯一, 其实就是根据对象的hashCodeequals方法来决定的, 如果我们往集合中存放自定义的对象, 那么保证其唯一, 就必须复写hashCode和equals方法建立属于当前对象的比较方式

HashSet存储自定义类型元素

给HashSet中存放自定义类型元素时, 需要重写对象的hashCodeequals方法, 建立自己的比较方式, 才能保证HashSet集合中的对象唯一

set集合不允许重复元素的原理

先调用hashcode方法判断哈希值是否相等, 若相等则为哈希冲突; 继续调用equals方法判断是否为同一对象

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;
    }
    @Override
    public boolean equals(Object o) {
   
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;
        Student student = (Student) o;
        return age == student.age &&
               Objects.equals(name, student.name
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值