前言:
接下来就到了JavaSE最重要的集合了,后面还有一个同样重要的多线程,基本上这两个算是JavaSE里蛮有分量的两个,知识点重要同时面试也是问的比较多的,面试题的话我会下一篇专门出一章,争取罗列的全面一点,这一章就简单的说说各个数据结构的特点、方法。
常见的数据结构:栈、队列、数组、链表、红黑树
栈(stack)
栈,又称堆栈,它是运算受限的线性表,其限制是仅允许在标的一段进行插入和删除操作,不允许在其他任何位置进行添加、查找、删除等操作。
- 特点:先进后出,栈的入口、出口都是栈的顶端位置。
- 压栈:存元素,即把元素存储到栈的顶端位置,栈中已有元素依次向栈底方向移动一个位置。
- 弹栈:取元素,即把栈的顶端位置的元素取出,栈中已有元素依次向栈顶方向移动一个位置。
队列(queue)
队列,简称队,它同堆栈一样,也是一种运算受限的线性表,其限制是仅允许在表的一端进行插入,而在表的另一端进行删除。
特点:先进先出
数组(Array)
数组,是有序的元素序列,数组是在内存中开辟一段连续的空间,并在此空间存放元素,就像是一排出租屋,有100个房间,从001到100每个房间都有固定的编号,通过编号就可以快速找到租屋子的人。
特点:
- 查找元素快,通过索引,可以快速访问指定位置的元素;
- 增删元素慢:
- 增元素:需要创建一个新数组,将指定新元素存储在指定索引位置,再把原数组元素根据索引,复制到新数组对应的索引位置。
- 删元素:需要创建一个新数组,把原数组元素根据索引,复制到新数组对应索引位置。原数组中指定索引位置元素不复制到新数组中。
链表
- 链表(linked list):由一系列节点node(链表中每一个元素称为节点)组成,结点可以在运行时动态生成,每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个节点地址的指针域。我们常说的链表结构有单向链表和双向链表。
- 特点:多个节点之间,通过地址进行连接。
- 查找元素慢:想查找某个元素,需要通过连接的节点,依次向后查找指定元素。
- 增删元素快:只需要修改连接下个元素的地址即可。
红黑树
二叉树(binary tree),是每个节点不超过2的有序树。
简单的理解:
就是一种类似于我们生活中树的结构,只不过每个结点上最多,只能有两个子结点,顶上的叫根节点,两边被称作“左子树”和“右子树”,红黑树属于二叉树的一种,红黑树本身就是一颗二叉查找输,将节点插入后,该树仍然是一颗二叉查找树,也就意味着,树的键值仍然是有序的。
特点:速度特别快,趋近平衡树,查找叶子元素最少和最多次数不多于二倍。
List集合
简介:java.util.List接口继承自Collection接口,是单列集合的一个重要分支。
特点:
- 允许出现重复元素;
- 集合中的元素排列有序,即存和取的顺序一致;
- 集合中的元素有索引,可以通过索引来随机访问元素。
方法:
public static void main(String[] args) {
List<String> list = new ArrayList<>(16);
list.add("hello");// 向集合中添加元素
list.add("world");
System.out.println(list.get(0));// 获取指定位置的元素 hello
System.out.println(list);// [hello, world]
list.remove(0);// 删除指定位置的元素
System.out.println(list);// [world]
// 用指定元素替换集合中指定位置的元素,返回值为更新前的元素,小心数组越界
list.set(0, "Hello");
System.out.println(list);// [Hello]
}
List子类
它之下的子类有Vector(已逐渐退出历史舞台)、ArrayList(常用)、LinkedList
ArrayList
java.util.ArrayList集合数据存储的结构是数组,元素增删慢,查找快,由于日常开发中使用最多的功能是查询数据、遍历数据,所以ArrayList是最常用的集合。不过要根据具体情况选择性的使用集合,业务的主要操作是增删、还是查找。
LinkedList
java.util.LinkedList集合数据存储的结构是链表结构,方便元素添加、删除的集合,这是一个双向链表。由于它额外的维护了一条链表,所以占用的内存空间也相对比较大。
public static void main(String[] args) {
LinkedList<String> list = new LinkedList<>();
list.add("a");
list.add("b");
list.addFirst("a0");
list.addLast("b1");
System.out.println(list);// [a0, a, b, b1]
// 只是偷窥一下第一个元素,并没有取出来
System.out.println(list.peek());// a0
System.out.println(list);// [a0, a, b, b1]
// 删除第一个元素
list.pop();
System.out.println(list);// [a, b, b1]
// 获取第一个元素
System.out.println(list.getFirst());// a
list.push("a0");// 在集合的最前面添加元素
System.out.println(list);// [a0, a, b, b1]
list.removeLast();
System.out.println(list);// [a0, a, b]
}
Set接口
简介:继承自Collection,没有扩充,只是更严格了。
特点:
- Set接口中元素无序
- 元素不允许重复(比较hashcode以及equals比较内存地址),取出元素不能用普通的for循环,可以采用迭代器,增强for
HashSet
HashSet是Set接口的一个实现类,它所存储的元素是不可以重复的,并且元素都是无序的(即存取顺不一致),底层是哈希表(数组+链表/红黑树)
HashSet是根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存取和查找性能。保证元素唯一性的方式依赖于:hashcode与equals方法。
什么是哈希表?
在JDK1.8之前,哈希表底层采用数组+链表实现,即使用链表处理冲突,同一 hash 值的链表都存储在一个链表里。但是当位于一个桶中的元素较多,即 hash 值相等的元素较多时,通过key 值依次查找的效率较低。而 JDK1.8 中,哈希表存储采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。
LinkedHashSet保证存储、取出元素的有序(链表+哈希表);
Collections
java.utils.Collections`是集合工具类,用来对集合进行操作。部分方法如下:
public static <T> boolean addAll(Collection<T> c, T... elements)
:往集合中添加
一些元素。public static void shuffle(List<?> list)
:打乱集合顺序。public static <T> void sort(List<T> list)
:将集合中元素按照默认规则排序。public static <T> void sort(List<T> list,Comparator<? super T> )
:将集合中元素按照指定规则排序。