目录
类集
链表
原理图
链表和二叉树伪代码结构
栈
队列
红黑树
Collection接口
List接口
ArrayList常用方法
Vector
LinkedList常用方法
Iterator与ListIterator
foreach
Set
Map
HashMap
HashMap实现原理
Java中Map常用方法总结以及遍历方式的汇总
Map三大常用功能方法表格整理
HashMap/Hashtable/ConcurrentHashMap/TreeMap/LinkedMap之间的区别
哈希表的初始容量和散列因子
存储自定义对象
JDK 9 集合新特性
类集
类集是什么:Java用于实现数据结构的库,在java.util包中。

链表
定义:链表 [Linked List]:链表是由一组不必相连(不必相连:可以连续也可以不连续)的内存结构(节点),按特定的顺序链接在一起的抽象数据类型。
原理图


链表和二叉树伪代码结构

栈

队列

红黑树

Collection接口
Collection 接口是在整个 Java 类集中保存单值的最大操作父接口,里面每次操作的时候都只能保存一个对象的数据。 此接口定义在 java.util 包中。

本接口中一共定义了 15 个方法,那么此接口的全部子类或子接口就将全部继承以上接口中的方法。
但是,在开发中不会直接使用 Collection 接口。而使用其操作的子接口:List、Set。
List接口
在整个集合中 List 是 Collection 的子接口,里面的所有内容都是允许重复的。

此接口的实现类,常用的实现类有如下几个:
ArrayList(95%)、Vector(4%)、LinkedList(1%)
-
Array和Vetor采用的是动态数组来存储,LinkList采用的是双向链表来实现,可以模拟栈和队列。
ArrayList常用方法
下面是总结了一些比较常用的ArrayList类成员方法:
-
增加元素到链表中
-
boolean add(Element e)增加指定元素到链表尾部. -
void add(int index, Element e)增加指定元素到链表指定位置.
-
-
从链表中删除元素
-
void clear()从链表中删除所有元素. -
E remove(int index)删除链表中指定位置的元素. -
protected void removeRange(int start, int end)删除链表中从某一个位置开始到某一个位置结束的元素。
-
-
获取链表中的元素
-
E get(int index)获取链表中指定位置处的元素. -
Object[] toArray()获取一个数组,数组中所有元素是链表中的元素.(即将链表转换为一个数组)
-
-
修改某个元素
-
E set(int index, E element)将链表中指定位置上的元素替换成新元素。
-
-
搜索元素
-
boolean contains(Object o)如果链表包含指定元素,返回true. -
int indexOf(Object o)返回元素在链表中第一次出现的位置,如果返回-1,表示链表中没有这个元素。 -
int lastIndexOf(Object o)返回元素在链表中最后一次出现的位置,如果返回-1,表示链表中没有这个元素。
-
-
检查链表是否为空
-
boolean isEmpty()返回true表示链表中没有任何元素.
-
-
获取链表大小
-
int size()返回链表长度(链表包含元素的个数).
-
以上是ArrayList类中使用比较多的成员方法。
Vector
方法与ArrayList基本相同
LinkedList常用方法
集合 的体系: ------------| Collection 单例集合的根接口 ----------------| List 如果是实现了List接口的集合类,具备的特点: 有序,可重复。 -------------------| ArrayList ArrayList 底层是维护了一个Object数组实现的。 特点: 查询速度快,增删慢。 -------------------| LinkedList LinkedList 底层是使用了链表数据结构实现的, 特点: 查询速度慢,增删快。 -------------------| Vector(了解即可) 底层也是维护了一个Object的数组实现的,实现与ArrayList是一样的,但是Vector是线程安全的,操作效率低。
----------------| Set 如果是实现了Set接口的集合类,具备的特点: 无序,不可重复。 -------------------| HashSet 底层是使用了哈希表来支持的,特点: 存取速度快. -------------------| TreeSet 如果元素具备自然顺序 的特性,那么就按照元素自然顺序的特性进行排序存储。
Linkedlist特有的方法: 1:方法介绍 addFirst(E e) addLast(E e)
getFirst() getLast()
removeFirst() removeLast()
2:数据结构 1:栈 (1.6) : 主要是用于实现堆栈数据结构的存储方式。 先进后出 push() pop() 2:队列(双端队列1.5): 主要是为了让你们可以使用LinkedList模拟队列数据结构的存储方式。 先进先出 offer() poll()
3:返回逆序的迭代器对象
descendingIterator() 返回逆序的迭代器对象
Iterator与ListIterator
//均用于取数据
//Iterator:适用于List和set
//ListIterator:只适用于List
ArrayList<Integer> data = new ArrayList<>();
data.add(1);
data.add(2);
data.add(3);
data.add(4);
data.add(5);
// Iterator<Integer> iterator = data.iterator();
// //迭代器使用的是指针
// //iterator.hasNext()是将指针指向下一个位置,看是否存在数据,返回的是布尔值
// /*
// while (iterator.hasNext()){
// Integer i =iterator.next();//iterator.next():将指针往下移动一个位置
// System.out.println(i);
// }
//
// iterator.next();
// //在remove前一定要用next()方法取到位置,因为只有这样把指针移动到有值得地方才能删除
// iterator.remove();
// System.out.println(data.size());
ListIterator<Integer> iterator = data.listIterator();
iterator.add(100); //添加是在索引0的前面添加,索引下面指针移动需要3次
iterator.next();//指针指向索引0
iterator.next();//指针指向索引1
iterator.set(200);
System.out.println(data.size());
iterator.previous();//指针从下往上移动一位
iterator.previous();
iterator.previous();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
foreach
-
foreach:增强For循环,最早出现在C#中
-
用于迭代数组 或 集合(Collection接口下的类)
-
语法:for(数据类型 变量名:集合或数组名){}
for (String s:set){ System.out.println(s); }
Set
-
不包含重复元素的集合。 更正式地说,集合不包含元素对
e1和e2,使得e1.equals(e2)和最多一个null元素。 正如其名称所暗示的,此接口模拟数学集抽象。 -
注意:如果将可变对象用作set元素,则必须非常小心。 如果在对象是集合中的元素时以影响equals比较的方式更改对象的值,则不指定集合的行为。
HashSet
储存数据的方式:以散列表的形式进行无序存放。
HashSet<String> set = new HashSet<>();
boolean flag1 =set.add("锄禾日当午");
set.add("汗滴禾下土");
set.add("谁知盘中餐");
set.add("粒粒皆辛苦");
boolean flag2 =set.add("锄禾日当午");
System.out.println(flag1);
System.out.println(flag2);//存入重复元素,返回false
Iterator<String> iterator = set.iterator();
for (String s:set){
//因为哈希表也是散列表,数据在散列表中的存储顺序不能确定,所以打印出来的
System.out.println(s);
}
//打印set里面的内容
/*while (iterator.hasNext()){
System.out.println(iterator.next());
}*/
TreeSet
-
储存数据的方式:以二叉树的形式进行有序存放。
-
排序是根据字符的ASCII码进行排序
TreeSet<String> data = new TreeSet<>();
data.add("b");
data.add("c");
data.add("a");
data.add("d");
for (String s:data){
System.out.println(s);
}
//System.out.println((char)1); //打印ASCII的方法
Map
-
collection是单值储存集合,map是双值储存集合(键值对)。
-
Map是将键映射到值的对象。 不能包含重复的键; 每个键最多可以映射一个值。
-
map集合的键(key)不可重复。大多数Set集合是用了map的键来存储数据,来实现数据的不可重复性。

HashMap
-
哈希表(hashmap),又称为散列表,是以对象数组+链表的形式进行储存。即把数组看作二维数组,在数组的某个索引中插入链表进行存储。其中,数组的索引我们又称为哈希桶。
-
如何得到哈希表?通过哈希码(hashcode)对数组长度取余,得到的余数就是数据存放的哈希桶编号。当有两个以上的数据放在同一个哈希桶中,那么就会使用链表的形式对这两个数据进行储存。
-
当哈希桶中的数据量大于8时,从链表转换为红黑二叉树
-
当哈希值中的数据量减少到6时,从红黑二叉树转换为链表
-
当哈希桶中的数据量等于7时,那么请问当数据量减少到6时,哈希表需要转换为链表吗?
-
我们确定哈希桶数据量为7时,该形式是二叉树还是链表。如果数据量为7时,还是链表,又怎么用得着转为链表呢
-
-
-
使用默认初始容量(16)和默认加载因子(0.75)构造一个空
HashMap。 -
散列因子的作用:当散列因子达到某阈值时,对象数组将进行动态扩容。比如下面这个初始桶数量为16,散列因子(加载因子)0.75,当数组的桶容量达到75%时,数组容量将扩大一倍,桶数量达到32.

HashMap实现原理


Java中Map常用方法总结以及遍历方式的汇总
一、整理:
看到array,就要想到角标。
看到link,就要想到first,last。
看到hash,就要想到hashCode,equals.
看到tree,就要想到两个接口。Comparable,Comparator。
二、Map与Collection在集合框架中属并列存在
1.Map存储的是键值对
2.Map存储元素使用put方法,Collection使用add方法
3.Map集合没有直接取出元素的方法,而是先转成Set集合,在通过迭代获取元素
4.Map集合中键要保证唯一性
也就是Collection是单列集合, Map 是双列集合。
总结:
Map一次存一对元素, Collection 一次存一个。Map 的键不能重复,保证唯一。
Map 一次存入一对元素,是以键值对的形式存在.键与值存在映射关系.一定要保证键的唯一性.
三、Map中常见方法:
1、添加:
1、V put(K key, V value) (可以相同的key值,但是添加的value值会覆
盖前面的,返回值是前一个,如果没有就返回null)
2、putAll(Map<? extends K,? extends V> m) 从指定映射中将所有映射关
系复制到此映射中(可选操作)。
2、删除
1、remove() 删除关联对象,指定key对象
2、clear() 清空集合对象
3、获取
1:value get(key); 可以用于判断键是否存在的情况。当指定的键不存在的时候,返
回的是null。
3、判断:
1、boolean isEmpty() 长度为0返回true否则false
2、boolean containsKey(Object key) 判断集合中是否包含指定的key
3、boolean containsValue(Object value) 判断集合中是否包含指定的value
4、长度:
Int size()
四、遍历Map的方式:
1、将map 集合中所有的键取出存入set集合。
Set<K> keySet() 返回所有的key对象的Set集合,再通过get方法获取键对应的值。
2、 values() ,获取所有的值.
Collection<V> values()不能获取到key对象
3、 Map.Entry对象 推荐使用 重点
Set<Map.Entry<k,v>> entrySet() 将map 集合中的键值映射关系打包成一个对象。
Map.Entry对象通过Map.Entry 对象的getKey,getValue获取其键和值。
第一种方式:使用keySet
将Map转成Set集合(keySet()),通过Set的迭代器取出Set集合中的每一个元素(Iterator)就是Map集合中的所有的键,再通过get方法获取键对应的值。
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class Demo1 {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "aaaa");
map.put(2, "bbbb");
map.put(3, "cccc");
System.out.println(map);
//
// 获取方法:
// 第一种方式: 使用keySet
// 需要分别获取key和value,没有面向对象的思想
// Set<K> keySet() 返回所有的key对象的Set集合
Set<Integer> ks = map.keySet();
Iterator<Integer> it = ks.iterator();
while (it.hasNext()) {
Integer key = it.next();
String value = map.get(key);
System.out.println("key=" + key + " value=" + value);
}
}
}
第二种方式: 通过values 获取所有值,不能获取到key对象
1 public static void main(String[] args) {
2 Map<Integer, String> map = new HashMap<Integer, String>();
3 map.put(1, "aaaa");
4 map.put(2, "bbbb");
5 map.put(3, "cccc");
6 System.out.println(map);
7 // 第二种方式:
8 // 通过values 获取所有值,不能获取到key对象
9 // Collection<V> values()
10
11 Collection<String> vs = map.values();
12 Iterator<String> it = vs.iterator();
13 while (it.hasNext()) {
14 String value = it.next();
15 System.out.println(" value=" + value);
16 }
17 }
第三种方式: Map.Entry
public static interface Map.Entry<K,V> 通过Map中的entrySet()方法获取存放Map.Entry<K,V>对象的Set集合。
Set<Map.Entry<K,V>> entrySet() 面向对象的思想将map集合中的键和值映射关系打包为一个对象,就是Map.Entry,将该对象存入Set集合,Map.Entry是一个对象,那么该对象具备的getKey,getValue获得键和值。
1 public static void main(String[] args) {
2 Map<Integer, String> map = new HashMap<Integer, String>();
3 map.put(1, "aaaa");
4 map.put(2, "bbbb");
5 map.put(3, "cccc");
6 System.out.println(map);
7 // 第三种方式: Map.Entry对象 推荐使用 重点
8 // Set<Map.Entry<K,V>> entrySet()
9
10
11 // 返回的Map.Entry对象的Set集合 Map.Entry包含了key和value对象
12 Set<Map.Entry<Integer, String>> es = map.entrySet();
13
14 Iterator<Map.Entry<Integer, String>> it = es.iterator();
15
16 while (it.hasNext()) {
17
18 // 返回的是封装了key和value对象的Map.Entry对象
19 Map.Entry<Integer, String> en = it.next();
20
21 // 获取Map.Entry对象中封装的key和value对象
22 Integer key = en.getKey();
23 String value = en.getValue();
24
25 System.out.println("key=" + key + " value=" + value);
26 }
27 }
Map三大常用功能方法表格整理
插入和删除元素(表 2 )。
表 2:Map 更新方法: 可以更改 Map 内容。
| clear() | 从 Map 中删除所有映射 |
|---|---|
| remove(Object key) | 从 Map 中删除键和关联的值 |
| put(Object key, Object value) | 将指定值与指定键相关联 |
| clear() | 从 Map 中删除所有映射 |
| putAll(Map t) | 将指定 Map 中的所有映射复制到此 map |
查看 Map
表 3:返回视图的 Map 方法: 使用这些方法返回的对象,您可以遍历 Map 的元素,还可以删除 Map 中的元素。
| entrySet() | 返回 Map 中所包含映射的 Set 视图。Set 中的每个元素都是一个 Map.Entry 对象,可以使用 getKey() 和 getValue() 方法(还有一个 setValue() 方法)访问后者的键元素和值元素 |
|---|---|
| keySet() | 返回 Map 中所包含键的 Set 视图。删除 Set 中的元素还将删除 Map 中相应的映射(键和值) |
| values() | 返回 map 中所包含值的 Collection 视图。删除 Collection 中的元素还将删除 Map 中相应的映射(键和值) |
访问元素
表 4:Map 访问和测试方法: 这些方法检索有关 Map 内容的信息但不更改 Map 内容。
| get(Object key) | 返回与指定键关联的值 |
|---|---|
| containsKey(Object key) | 如果 Map 包含指定键的映射,则返回 true |
| containsValue(Object value) | 如果此 Map 将一个或多个键映射到指定值,则返回 true |
| isEmpty() | 如果 Map 不包含键-值映射,则返回 true |
| size() | 返回 Map 中的键-值映射的数目 |
HashMap/Hashtable/ConcurrentHashMap/TreeMap/LinkedMap之间的区别
他们的区别主要在于线程安全的问题
HashMap:线程不安全,但效率快。如图1
Hashtable:线程安全,但效率慢。如图2
ConcurrentHashMap:采用分段锁机制,保证线程安全,效率又比较高,如图3
TreeMap:有序的排队集合
LinkedMap:采用哈下表+双向链表的结构,能够保证按元素添加的顺序进行存储。但是HashMap不会,比如说先存放的元素可能被存放于索引较后的数组中。

(图1)
如图1所示,ABC是同时独立操作数据,这样会造成数据错乱等线程不安全问题。比如:A往hashMap存了半碗水,然后B把A存的这半碗水取出来喝掉了,C往hashmap中存了半碗水。而A是不知道B,C的存在的,那么他就以为C存的那半碗水是自己存的那半碗。这样就是数据错乱问题。
hashmap允许同时操作数据,效率高,如果只是只做存或只做取数据时,hashmap不会有线程不安全问题。

图2
Hashtable采用的是顺序操作模式,能够有效防止数据错乱的问题,但是效率低。

图3
ConcurrentHashMap采用的是哈希表进行储存,首先通过对象数组的索引进行存储数据,这一步是不用顺序操作的,能够同步进行,因为数组的各个索引内容互不干扰。而在数组内部的哈希桶中,是采用顺序操作的方式,来保证数据不发生错乱。
哈希表的初始容量和散列因子
HashMap的实例有两个影响其性能的参数: 初始容量和负载因子 。 容量是哈希表中的桶数,初始容量只是创建哈希表时的容量。 加载因子是在自动增加容量之前允许哈希表获取的完整程度的度量。 当哈希表中的条目数超过加载因子和当前容量的乘积时,哈希表将被重新哈希(即,重建内部数据结构),以便哈希表具有大约两倍的桶数。
-
散列因子越大,越节省空间,但查询效率低
-
散列因子越小,越浪费空间,但查询效率高。
存储自定义对象
-
当我们以HashMap存储数据时,不应该更改其key的值。
-
如果确实要更改,那么就不要用hashMap这种数据结构来存储key。
HashMap<Book,String> data = new HashMap<Book, String>();
Book book1 = new Book("金苹果","讲述了苹果种植的辛酸路程");
data.put(book1,"我们人生的第一本书");
Book book2 = new Book("银苹果","讲述了苹果种植的辛酸路程");
data.put(book2,"我们人生的第二本书");
//哈希值是通过key和value计算出来的。
// 因为下面更改了key(book1),哈希值重新计算了,没有找到之前存放数据的哈希桶,从而没有找到value,返回null。
book1.setName("铜苹果");
System.out.println(data.get(book1));
//更可怕的是,当数据存到一定量时,哈希表重新散列。此时book1的键会重新按照铜苹果进行存储。
//这样又会出现我们一直以为key是金苹果,但实际是铜苹果这种尴尬的问题。
Book book3 = new Book("金苹果","讲述了苹果种植的辛酸路程");
//按道理,我们通过book3的键对去取,应该能找到Book1的value("我们人生的第一本书")
//除了要比较哈希值,系统还有比较equals。
// 虽然Book1和Book3的哈希值可能相同,但是因为Book1把name改为了铜苹果,所以equals为False,也是同样地找不到数据
System.out.println(data.get(book3));
//因此,当我们以HashMap存储数据时,不应该更改其key的值。
// 如果确实要更改,那么就不要用hashMap这种数据结构来存储key。
JDK 9 集合新特性
//JDK 9 集合新特性:List,Set,HashMap均有of()方法来设置内容
//集合长度一旦设定了,不可修改。
public static void main(String[] args) {
List<String> list = List.of("锄禾日当午","汗滴禾下土");
//list.add("谁知盘中餐");//由于集合长度一旦设定了,不可修改的特性,运行此代码时会报错。
for (String s : list){
System.out.println(s);
}
Set<String> set = Set.of("一二三四五","上山打老虎");
for (String s : set){
System.out.println(s);
}
Map<String,String> map = Map.of("haha1","锄禾日当午","haha2","汗滴禾下土");
Set<String> keyset = map.keySet();
for (String key:keyset){
System.out.println(key+"->"+map.get(key));
}
}
最后
以上就是大力红牛最近收集整理的关于JavaEE笔记——集合类集链表栈队列红黑树Collection接口Map的全部内容,更多相关JavaEE笔记——集合类集链表栈队列红黑树Collection接口Map内容请搜索靠谱客的其他文章。
发表评论 取消回复