数据结构
栈
- stack,又称堆栈,它是运算受限的线性表,其限制是仅允许在标的一端进行插入和删除操作,不允许在其他任何位置进行添加、查找、删除等操作。
- 先进后出,即存进去的元素,要在后它后面的元素依次取出后,才能取出该元素。
- 栈的入口、出口的都是栈的顶端位置。
- 压栈:就是存元素。即,把元素存储到栈的顶端位置,栈中已有元素依次向栈底方向移动一个位置。
- 弹栈:就是取元素。即,把栈的顶端位置元素取出,栈中已有元素依次向栈顶方向移动一个位置。
队列
- queue,简称队,它同堆栈一样,也是一种运算受限的线性表,其限制是仅允许在表的一端进行插入,而在表的另一端进行删除。
- 先进先出,即存进去的元素,要在后它前面的元素依次取出后,才能取出该元素。
- 队列的入口、出口各占一侧。
数组
- Array,是有序的元素序列,数组是在内存中开辟一段连续的空间,并在此空间存放元素。
- 查找元素快:数组的地址是连续的,通过数组的首地址可以找到数组,通过索引,可以快速访问指定位置的元素。
- 增删元素慢:数组的长度是固定的,想要增加/删除一个元素,必须创建一个新数组,把原数组元素根据索引,复制到新数组对应索引的位置。
- 在堆内存中,频繁的创建数组,复制数组中的元素,销毁数组,效率低下。
链表
- linked list,由一系列结点node(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。
- 单向链表:结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。不能保证元素的顺序。
- 双向链表:链表中有两条链子,有一条专门记录元素的顺序,是一个有序的集合。
- 查找元素慢:链表地址不是连续的,想查找某个元素,需要从头开始。通过连接的节点,依次向后查找指定元素。
- 增删元素快:只需要修改连接下个元素的地址即可。
红黑树
- 二叉树:binary tree ,是每个结点不超过2的有序树(tree) 。顶上的叫根结点,两边被称作“左子树”和“右子树”。
- 红黑树本身就是一颗二叉查找树,将节点插入后,该树仍然是一颗二叉查找树。也就意味着,树的键值仍然是有序的。
- 红黑树的约束:节点可以是红色的或者黑色的;根节点是黑色的;叶子节点(特指空节点)是黑色的;每个红色节点的子节点都是黑色的;任何一个节点到其每一个叶子节点的所有路径上黑色节点数相同。
- 红黑树的特点:查询速度特别快,趋近平衡树,查找叶子元素最少和最多次数不多于二倍。
数组
动态初始化格式
数据类型[] 数组名 = new 数据类型[数组长度];
int[] arr = new int[3];
静态初始化格式
数据类型[] 数组名 = new 数据类型[] {元素1,元素2,…};
省略格式
数据类型[] 数组名 = {元素1,元素2,…};
访问数组元素格式
数组名[索引]; (索引从0开始)
注意
- 动态初始化格式的数据,元素拥有一个默认值,规则为:整数类型,默认为0;浮点类型,默认为0.0;字符类型,默认为’\u0000‘;布尔类型,默认为false;引用类型,默认为null。
- 数组赋值格式 :数组名[索引] = 值;
- 数组的长度:int len = 数组名.length;
- 数组的反转
public static void reverse(int[] arr) {
//循环遍历数组,是开始索引小于等于结束索引
for (int start = 0, end = arr.length - 1; start < end; start++, end--) {
//变量交换
int temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
}
}
Iterator接口
//创建一个集合对象
Collection<String> coll = new ArrayList<>();
coll.add("000");
//多态 接口 实现类对象
Iterator<String> it = coll.iterator(); // 把指针(索引)集合指向-1
while(it.hasNext()){
String e = it.next();
System.out.println(e);
}
System.out.println("----------------------");
for(Iterator<String> it2 = coll.iterator();it2.hasNext();){
String e = it2.next();
System.out.println(e);
}
- 也是Java集合中的一员,主要用于迭代访问(即遍历) Collection 中的元素,因此 Iterator 对象也被称为迭代器。
- 迭代:在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断。一直把集合中的所有元素全部取出。
- 在进行集合元素取出时,如果集合中已经没有元素了,还继续使用迭代器的next方法,将会报错。
增强for
for(元素的数据类型 变量 : Collection集合or数组){
//写操作代码
}
- 增强for循环(也称for each循环)是JDK1.5以后出来的一个高级for循环,专门用来遍历数组和集合的。它的内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。
Collection接口
单列集合类的根接口,用于存储一系列符合某种规则的元素,它有两个重要的子接口,分别是List 和 Set 。其中 List 的特点是元素有序、元素可重复。 Set 的特点是元素无序,而且不可重复。
List接口
- 是一个元素存取有序的集合。
- 是一个带有索引的集合,通过索引就可以精确的操作集合中的元素。
- 可以有重复的元素。
Set接口
- 不允许存储重复元素。
- 没有索引,没有带索引的方法,也不能使用普通的for循环遍历。
ArrayList集合
- 底层是数组实现的,长度可以变化。(元素增删慢,查找快)
- 尖括号泛型,只能是引用类型,不能是基本类型。
- 直接打印输出得到的是内容,不是地址值。
LinkedList集合
- 数据存储的结构是链表结构(双向链表)。查询慢,增删快。
- 含有大量操作首尾元素的方法。(不能使用多态)
HashSet集合
- 底层是一个哈希表结构,查询速度快。(根据对象的哈希值来确定元素在集合中的存储位置)
- 无序集合,存储和去除元素的顺序有可能不一致。(允许使用null元素)
哈希值
- 是一个十进制的整数,由系统随机给出。(对象的地址值,是一个逻辑地址,是模拟出来得到的地址,不是数据实际存储的物理地址)
- 在Object类中hashCode()方法可以获取对象的哈希码值。
哈希表
- 在JDK1.8之前,哈希表底层采用数组+链表实现,即使用数组把元素进行分组(相同哈希值的元素一组),使用链表处理哈希冲突,同一hash值的链表都存储在一个链表里。
- 在JDK1.8中,哈希表存储采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。(当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。因此添加了红黑树)
- 存储原理:如set集合调用add方法时,add方法会调用元素的hashCode()方法计算哈希值,没有重复的哈希值,则直接存储。有重复哈希值,则调用元素的equals方法比较,为true元素相同,不会存储;为false不相同,则会将元素挂到相同哈希值元素下面(链表或红黑树)。(前提:存储元素重写了hashCode和equals方法)
LinkedHashSet集合
- 继承HashSet集合。
- 底层结构是链表(记录元素的存储顺序)和哈希表。保证元素有序。
比较器
- Collections 是集合工具类,里面sort对List集合进行排序。
- 比较结果有三种:大于,等于,小于。如果要按照升序排序, 则o1 小于o2,返回(负数),相等返回0,o1大于o2返回(正数) 如果要按照降序排序 则o1 小于o2,返回(正数),相等返回0,o1大于o2返回(负数)。(此处o1在compareTo方法里是this)
Comparable接口
被排序的集合里面的元素,必须实现Comparable,重写compareTo方法来定义排序规则。(只能一种排序规则)
Comparator接口
直接在sort方法里匿名内部类创建排序规则。(可以调用sort方法多次更改排序规则)
Map接口
- Collection 中的集合称为单列集合, Map 中的集合称为双列集合,包含两个值,一个key,一个value。
- Map接口有多个子类,常用的HashMap集合、LinkedHashMap集合。
- Map集合中的元素,key和value的数据类型可以形同,也可以不同。
- Map集合中的元素,key是不允许重复的,value是可以重复的。
- Map集合中的元素,key和value是一一对应的。
- Map直接输出打印的是map内容。
常用方法
- put方法返回值:添加key不重复时,返回值是null;添加key重复时,会使用新的value替换map中重复key的value,返回值是被替换的value值。
- remove方法返回值:删除key存在,返回值是被删除的value值;删除key不存在,返回值是null。
- get方法返回值同remove方法。
Entry键值对对象
- Map.Entry<K,V>:在Map接口中有一个内部接口Entry。当Map集合一创建,就会创建一个Entry对象,用来记录键与值。
- public K getKey() :获取Entry对象中的键。public V getValue() :获取Entry对象中的值。
遍历:键值对方式
- 根据entrySet()方法,把Map集合内部多个Entry对象取出来存储到set集合中。
- 遍历包含键值对(Entry)对象的Set集合,得到每一个键值对(Entry)对象。
- 通过键值对(Entry)对象,获取Entry对象中的键与值。getkey() getValue()
遍历:键找值方式
- 由于键是唯一的,根据keyset()方法获取一个Set集合存储所有的键。
- 遍历键的Set集合,得到每一个键。
- 根据键,get(key)获取键所对应的值。
HashMap集合
- 存储数据采用的哈希表结构,查询速度快。(JDK1.8之前是数组+单向链表。JDK1.8之后是数组+单向链表/红黑树(链表长度超过8时)。提高查询速度)
- 无序集合,元素的存取顺序不能保证一致。
LinkedHashMap集合
- 继承HashMap,底层是哈希表+链表结构,保证迭代的顺序。
- 有序集合,存储和取出元素的顺序一致。
Hashtable集合
- 底层是一个哈希表,是一个线程安全的集合,是单线程集合,速度慢;HashMap底层也是哈希表,是一个线程不安全的集合,是多线程集合,速度快。
- 不能存储null值,null键;HashMap(上面的其他集合)可以存储null值,null键。