Java集合学习总结
常见的数据结构
数据存储的常用结构有:栈、队列、数组、链表和红黑树
栈
·栈:Stack,又称为栈它是运算受限的线性表,其限制是仅允许在表的一端进行插入和删除操作,不允许在其他任何位置进行添加、查找、删除等操作
简单的说:采用该结构的集合,对元素的存取有如下的特点:
1、先进后出(即,存进去的元素,要在它后面的元素依次取出后,才能取出该元素)。例如,子弹压进弹夹,先压进去的子弹在下面,后压进去的子弹在上面,当开枪时,先弹出上面的子弹,然后才能取出下面的子弹
2、栈的入口、出口都是栈的顶端位置
队列
·队列:queue,简称队,它同栈一样,也是一种运算受限的线性表,其限制是允许在表的一端进行插入,而在表的另一端进行删除
简单的说:采用该结构的集合,对元素的存取有如下特点:
1、先进先出(即,存进去的元素要在它前面的元素依次取出后,才能取出该元素)。例如,小火车过山洞,车头先进去,车尾后进去;车头先出来,车尾后出来
2、队列的入口、出口各占一侧
数组
·数组:Array,是有序的元素序列,数组是在内存中开辟一段连续的空间,并在此空间存放元素。就像是一排出租屋,有100个房间,从001到100每个房间都有固定编号,通过编号就可以快速找到租房子的人。
简单的说:采用该结构的集合,对元素的存取有如下的特点:
1、查找速度快:通过索引,可以快速访问指定位置的元素
2、增删元素慢
指定索引位置增加元素:需要创建一个新数组,将指定新元素存储在指定索引位置,再把原数组元素根据索引,复制到新数组对应索引的位置。
链表
·链表 :linked list,由一系列节点node(链表中每一个元素称为节点),节点在运行时可以动态生成,每个节点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个节点地址的指针域。我们常说的链表结构有单向链表与双向链表。
简单的说,采用该结构的集合,对元素的存取有如下的特点:
1、多个节点之间,通过地址进行链接。例如自行车链。
2、查找元素慢:想查找某个元素,需要通过连接的节点,一次向后查找指定元素(每次查询都必须从头开始查询)
3、增删元素快
·增加元素:只需要修改连接下个元素的地址即可
单向链表:链表中只有一条链子,不能保证元素的顺序(存储元素和取出元素的顺序有可能不一致)
双向链表:链表中有两条链子,有一条链子是专门记录元素的顺序,是一个有序的集合
红黑树
(特点:趋近于平衡树,查询的速度非常快,查询叶子节点最大次数和最小次数不能超过2倍)
·二叉树:binary tree,是每个节点不超过2的有序树(tree)
简单的理解:就是一种类似于我们生活中树的结构,只不过每个节点上都最多只能有两个子节点。
二叉树是每个节点最多有两个子树的结构,顶上的叫根节点,两边被称作“左子树”和“右子树”
·查找树/排序树
在二叉树的基础上,元素是有大小顺序的
左子树小,右子树大
Collection
常用方法介绍
java.util.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):将集合中元素按照指定规则排序
定义的是所有单列集合中共性的方法
所有的单值集合都可以使用共性的方法
List
List接口介绍
java.util.List接口继承自Collection接口,是单列集合的一个重要分支,习惯性地会将实现了List接口的对象称为List集合。在List集合中允许出现重复的元素,所有的元素是以一种线性方式进行存储的,在程序中可以通过索引来访问集合中的指定元素。另外,List集合还有一个特点就是元素有序,即元素的存入顺序和取出顺序一致。
List接口的特点:
1、它是一个元素存取有序的集合。例如,存元素的顺序是11、22、33。那么集合中,元素的存储就是按照11、22、33的顺序完成的。
2、它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是一个道理)
3、集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素
ArrayList集合
java.util.ArrayList集合数据存储的结构是数组结构。元素增删慢,查找快,由于日常开发中使用最多的功能为查询数据、遍历数据,所以ArrayList是最常用的集合
LinkedList集合
java.util.LinkedList集合数据存储的结构是链表结构。方便元素增加、删除的集合
LinkedList是一个双向链表(实际开发中对一个集合元素的添加与删除经常涉及到首位操作)
Set
(是单列集合的一种)
1、不允许存储重复的元素、存取无序
2、没有索引(不能使用普通的for循环遍历)
Set接口中有一下子类:HashSet、LinkedHashSet、TreeSet
HashSet:底层是哈希表+(红黑树)实现的,无索引、不可以存储重复元素,存取无序
LinkedHashSet:底层是哈希表+链表实现的,无索引,不可以存储重复元素,可以保证存取顺序
TreeSet:底层是二叉树实现。一般用于排序
HashSet集合介绍
java.util.Set接口和java.util.List接口一样,同样继承自Collection接口,它与Collection接口中的方法基本一致,并没有对Collection接口进行功能上的扩充,只是比Collection接口更加严格。与List接口不同的是,Set接口中元素无序,并且都会以某种规则保证存入的元素不重复。
Set集合有多个子类,这里我们介绍其中的java.util.HashSet、java.util.LinkedHashSet这两个集合。
注释:Set集合取出元素的方式可以采用:迭代器、增强for。
java.util.HashSet是Set接口的一个实现类,它所存储的元素是不可重复的,并且元素都是无序的(即存取顺序不一致)。java.util.HashSet底层的实现其实是一个java.util.HashMap支持,
HashSet是根据对象的哈希值来确定元素在集合中的存储位置,因为具有良好的存取和查找性能。保证元素唯一性的方式依赖于:hashCode与equals方法
HashSet集合存储数据的结构(哈希表)
什么是哈希表?
在JDK1.8之前,哈希表底层采用数组+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里。但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率低。而JDK1.8中,哈希表存储采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查询时间。链表长度减少阈值(6)时,转换为链表。
简单的说,哈希表是由数组+链表+红黑树(JDK1.8增加了红黑树部分)实现的
set集合存储元素不重复的元素(例,存储自定义类型的元素:Person、Student)
前提:存储的元素必须重写hashCode方法和equals方法。比较方式:首先比较hashCode值是否相同,不同则在对应数组中hashCode值中存储元素。若相同,再比较equals方法,若相同则不进行存储,若不同则在对应数组中hashCode值中存储元素
LinkedHashSet集合
/** * java.util.LinkedHashSet集合 extends HashSet集合 * LinkedHashSet集合的特点: * 底层是一个哈希表(数组+链表/红黑树)+链表:多了一条链表(记录元素的存储顺序) * 保证元素有序 */
Map
Map集合的特点
1、Map集合是一个双列集合,一个元素包含两个值(一个key,一个value)
2、Map集合中的元素,key和value的数据类型可以相同,可以不同
3、Map集合中的元素,key是不允许重复的,value是可以重复的
4、Map集合中的元素,key和value是一一对应的
Map常用子类
主要HashMap集合、LinkedHashMap集合、TreeMap集合
·HashMap<K,V>:存储数据采用的是哈希表结构(查询速度非常快-数组+单向列表/红黑树(阈值>8)),元素的存取顺序不能保证一致。由于要保证键的唯一、不重复,需要重写键的hashCode()方法、equals()方法
java.util.hashMap<K,V>集合 implements Map<K,V>接口
HashMap是一个无序的集合,存储元素和取出元素的顺序有可能不一致
·LinkedHashMap<K,V>:HashMap下有一个子类LinkedHashMap,存储数据采用的是哈希表结构+链表结构(保证迭代的顺序)。通过链表结构可以保证元素的存取顺序一致;通过哈希结构可以保证键的唯一、不重复,需要写键的hashCode()方法、equals()方法
LinkedHashMap集合是一个有序的集合,存储和取出元素的顺序是一致的
tips:Map接口中的集合有两个泛型变量<K,V>,在使用时,要为两个泛型变量赋值数据类型。两个泛型变量<K,V>的数据类型可以相同,也可以不同
Map接口中的常用方法
·public V put (K key,V value):把指定的键与指定的值添加到Map集合中
·public V remove(Object key):把指定的键所对应的键值对元素在Map集合中删除,返回被删除元素的值
·public V get(Object key):根据指定的键,在Map集合中获取对应的值
·boolean containsKey(Object key):判断集合中是否包含指定的键
·public Set<K> keySet():获取Map集合中所有的键,存储到Set集合中
·public Set<Map.Entry<K,V>> extrySet():获取到Map集合中所有的键值对对象的集合(Set集合)Map集合遍历键找值方式
键找值方式:即通过元素中的键,获取键所对应的值
分析步骤:
1、获取Map集合中所有的键,由于键是唯一的所以返回一个Set(不允许存储重复的元素)集合存储所有的键。方法提示:keySet()
2、遍历键的Set集合,得到每一个键
3、根据键,获取键所对应的值。方法提示:get(K key)
Entry键值对对象
我们已经知道,Map集合中存放的是两种对象,一种称为key(键),一种称为value(值),它们在Map集合中是一一对应的关系,这一对对象又称做Map中的一个Entry(项)。Entry将键值对的对应关系封装成了对象。即键值对对象,这样我们在遍历Map集合时,就可以从每一个键值对(Entry)对象中获取对应的键与对应的值。
既然Entry表示了一对键和值,那么也同样提供了获取对应键和对应值的方法:
·public K getKey():获取Entry对象中的键
·public V getValue():获取Entry对象中的值
Map集合遍历键值对方式
Map.Entry<K,V>:在Map接口中有一个内部接口Entry
作用:当Map集合一创建,那么就会在Map集合中创建一个Entry对象,用来记录键与值(键值对对象,键与值的映射关系)--->结婚证
LinkedHashMap
java.util.LinkedHashMap<K,V> extends HashMap<K,V>
Map接口的哈希表和链接列表实现的,具有可预知的迭代顺序
底层原理:
哈希表+链表(记录元素顺序)
HashTable
/** * java.util.hashTable<K,V> implements Map<K,V> * HashTable:底层也是哈希表,是一个线程安全的集合,是单线程集合,速度慢 * HashMap:底层是哈希表,是一个线程不安全的集合,是多线程集合,速度快 * * HashMap集合(之前学的所有集合):可以存储null值和null键 * HashTable集合不能存储null值和null键 * * HashTable和Vector集合一样,在jdk1.2版本之后被更先进的集合(HashMap和ArrayList)取代了 * HashTable的子类Properties依然活跃在历史舞台 * Properties集合是一个唯一和IO流相结合的集合 */
CurrentHashMap
采用分段同步的策略,性能介于HashMap和HashTable之间
Iterator迭代器
java.util.Iterator接口:迭代器(对集合进行遍历)
有两个常用的方法
boolean hasNext() 如果仍有元素可以迭代,则返回true。(判断集合中还有没有下一个元素,有就返回true,没有就返回false)
E next() 返回迭代的下一个元素。(取出集合中下一个元素)
Iterator迭代器,是一个接口,我们无法直接使用,需要使用Iterator接口的实现类对象,获取实现类的方式比较特殊。Collection接口中有一个方法叫iterator(),这个方法返回的就是迭代器的实现类对象
Iterator<E> iterator() 返回在此collection的元素上进行迭代的迭代器
迭代器的使用步骤:
1、使用集合中的方法iterator()获取迭代器的实现类对象,使用Iterator接口接收(多态)
2、使用iterator接口中的方法hasNext判断还有没有下一个元素
3、使用iterator接口中的方法next取出集合中的下一个元素
其他
使用HashSet和HashMap必须注意,HashSet的值和HashMap的Key值,尽量不使用可变参数。使用可变参数,会导致当参数变更时,参数的HashCode值也跟着发生变化,从而找不到元素。