JAVA集合框架

数据结构
早在 Java 2 中之前,Java 就提供了特设类。比如:Dictionary, Vector, Stack, 和 Properties 这些类用来存储和操作对象组。
虽然这些类都非常有用,但是它们缺少一个核心的,统一的主题。由于这个原因,使用 Vector 类的方式和使用 Properties 类的方式有着很大不同。
集合框架被设计成要满足以下几个目标。
- 该框架必须是高性能的。基本集合(动态数组,链表,树,哈希表)的实现也必须是高效的。
- 该框架允许不同类型的集合,以类似的方式工作,具有高度的互操作性。
- 对一个集合的扩展和适应必须是简单的。
为此,整个集合框架就围绕一组标准接口而设计。你可以直接使用这些接口的标准实现,诸如: LinkedList, HashSet, 和 TreeSet 等,除此之外你也可以通过这些接口实现自己的集合。

从上面的集合框架图可以看到,Java 集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射。Collection 接口又有 3 种子类型,List、Set 和 Queue,再下面是一些抽象类,最后是具体实现类,常用的有 ArrayList、LinkedList、HashSet、LinkedHashSet、HashMap、LinkedHashMap 等等。
集合框架是一个用来代表和操纵集合的统一架构。所有的集合框架都包含如下内容:
-
**接口:**是代表集合的抽象数据类型。例如 Collection、List、Set、Map 等。之所以定义多个接口,是为了以不同的方式操作集合对象
-
**实现(类):**是集合接口的具体实现。从本质上讲,它们是可重复使用的数据结构,例如:ArrayList、LinkedList、HashSet、HashMap。
-
**算法:**是实现集合接口的对象里的方法执行的一些有用的计算,例如:搜索和排序。这些算法被称为多态,那是因为相同的方法可以在相似的接口上有着不同的实现。
除了集合,该框架也定义了几个 Map 接口和类。Map 里存储的是键/值对。尽管 Map 不是集合,但是它们完全整合在集合中。
集合框架体系如图所示

Java 集合框架提供了一套性能优良,使用方便的接口和类,java集合框架位于java.util包中, 所以当使用集合框架的时候需要进行导包。
集合接口
集合框架定义了一些接口。本节提供了每个接口的概述:
| 序号 | 接口描述 |
|---|---|
| 1 | Collection 接口 Collection 是最基本的集合接口,一个 Collection 代表一组 Object,即 Collection 的元素, Java不提供直接继承自Collection的类,只提供继承于的子接口(如List和set)。Collection 接口存储一组不唯一,无序的对象。 |
| 2 | List 接口 List接口是一个有序的 Collection,使用此接口能够精确的控制每个元素插入的位置,能够通过索引(元素在List中位置,类似于数组的下标)来访问List中的元素,第一个元素的索引为 0,而且允许有相同的元素。List 接口存储一组不唯一,有序(插入顺序)的对象。 |
| 3 | Set Set 具有与 Collection 完全一样的接口,只是行为上不同,Set 不保存重复的元素。Set 接口存储一组唯一,无序的对象。 |
| 4 | SortedSet 继承于Set保存有序的集合。 |
| 5 | Map Map 接口存储一组键值对象,提供key(键)到value(值)的映射。 |
| 6 | Map.Entry 描述在一个Map中的一个元素(键/值对)。是一个 Map 的内部接口。 |
| 7 | SortedMap 继承于 Map,使 Key 保持在升序排列。 |
| 8 | Enumeration 这是一个传统的接口和定义的方法,通过它可以枚举(一次获得一个)对象集合中的元素。这个传统接口已被迭代器取代。 |
集合实现类(集合类)
Java提供了一套实现了Collection接口的标准集合类。其中一些是具体类,这些类可以直接拿来使用,而另外一些是抽象类,提供了接口的部分实现。
标准集合类汇总于下表:
| 序号 | 类描述 |
|---|---|
| 1 | AbstractCollection 实现了大部分的集合接口。 |
| 2 | AbstractList 继承于AbstractCollection 并且实现了大部分List接口。 |
| 3 | AbstractSequentialList 继承于 AbstractList ,提供了对数据元素的链式访问而不是随机访问。 |
| 4 | LinkedList 该类实现了List接口,允许有null(空)元素。主要用于创建链表数据结构,该类没有同步方法,如果多个线程同时访问一个List,则必须自己实现访问同步,解决方法就是在创建List时候构造一个同步的List。例如:List list=Collections.synchronizedList(newLinkedList(...));LinkedList 查找效率低。 |
| 5 | ArrayList 该类也是实现了List的接口,实现了可变大小的数组,随机访问和遍历元素时,提供更好的性能。该类也是非同步的,在多线程的情况下不要使用。ArrayList 增长当前长度的50%,插入删除效率低。 |
| 6 | AbstractSet 继承于AbstractCollection 并且实现了大部分Set接口。 |
| 7 | HashSet 该类实现了Set接口,不允许出现重复元素,不保证集合中元素的顺序,允许包含值为null的元素,但最多只能一个。 |
| 8 | LinkedHashSet 具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现。 |
| 9 | TreeSet 该类实现了Set接口,可以实现排序等功能。 |
| 10 | AbstractMap 实现了大部分的Map接口。 |
| 11 | HashMap HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。 该类实现了Map接口,根据键的HashCode值存储数据,具有很快的访问速度,最多允许一条记录的键为null,不支持线程同步。 |
| 12 | TreeMap 继承了AbstractMap,并且使用一颗树。 |
| 13 | WeakHashMap 继承AbstractMap类,使用弱密钥的哈希表。 |
| 14 | LinkedHashMap 继承于HashMap,使用元素的自然顺序对元素进行排序. |
| 15 | IdentityHashMap 继承AbstractMap类,比较文档时使用引用相等。 |
在前面的教程中已经讨论通过java.util包中定义的类,如下所示:
| 序号 | 类描述 |
|---|---|
| 1 | Vector 该类和ArrayList非常相似,但是该类是同步的,可以用在多线程的情况,该类允许设置默认的增长长度,默认扩容方式为原来的2倍。 |
| 2 | Stack 栈是Vector的一个子类,它实现了一个标准的后进先出的栈。 |
| 3 | Dictionary Dictionary 类是一个抽象类,用来存储键/值对,作用和Map类相似。 |
| 4 | Hashtable Hashtable 是 Dictionary(字典) 类的子类,位于 java.util 包中。 |
| 5 | Properties Properties 继承于 Hashtable,表示一个持久的属性集,属性列表中每个键及其对应值都是一个字符串。 |
| 6 | BitSet 一个Bitset类创建一种特殊类型的数组来保存位值。BitSet中数组大小会随需要增加。 |
集合算法
集合框架定义了几种算法,可用于集合和映射。这些算法被定义为集合类的静态方法。
在尝试比较不兼容的类型时,一些方法能够抛出 ClassCastException异常。当试图修改一个不可修改的集合时,抛出UnsupportedOperationException异常。
集合定义三个静态的变量:EMPTY_SET,EMPTY_LIST,EMPTY_MAP的。这些变量都不可改变。
| 序号 | 算法描述 |
|---|---|
| 1 | Collection Algorithms 这里是一个列表中的所有算法实现。 |
迭代器的使用
通常情况下,你会希望遍历一个集合中的元素。例如,显示集合中的每个元素。
一般遍历数组都是采用for循环或者增强for,这两个方法也可以用在集合框架,但是还有一种方法是采用迭代器遍历集合框架,它是一个对象,实现了Iterator 接口或 ListIterator接口。
迭代器,使你能够通过循环来得到或删除集合的元素。ListIterator 继承了 Iterator,以允许双向遍历列表和修改元素。
| 序号 | 迭代器方法描述 |
|---|---|
| 1 | 使用 Java Iterator 这里通过实例列出 Iterator 和 ListIterator 接口提供的所有方法。 |
单列集合Collection
是单列集合的顶层接口
ArrayList
ArrayList源代码中ArrayList继承了AbstractList
ArrayList实现了接口List

list可以存储任意的数据类型
数据类型及对象的存储
public class ArrayListTest {
@Test
public void test01(){
// 接口的引用指向实现类的实例化对象
List list = new ArrayList();
byte a = 1;
short b = 2;
int c = 3;
long d = 4L;
double e = 5.0d;
float f = 6.0f;
char g = 'a';
boolean h = false;
// 存储一个对象
Person person = new Person();
list.add(a);
list.add(b);
list.add(c);
list.add(d);
list.add(c);
list.add(d);
list.add(e);
list.add(f);
list.add(g);
list.add(h);
list.add(person);
list.add(a);
System.out.println(list.size());
}
获取存储的元素个数输出
12
以上元素中有重复的值存入,因为底层源代码中是Object[]数组,
所以数组中有下标 可以根据不同的下标找到不同的值,值也是可以重复的


根据下标index获取对应位置上元素的值
获取存储元素的值
public class ArrayListTest {
@Test
public void test02(){
List list = new ArrayList();
list.add("张三");
System.out.println(list.get(0));
}
}
如果获取数组下标没有的数据的值时,系统会报异常
public class ArrayListTest {
@Test
public void test02(){
List list = new ArrayList();
list.add("张三");
System.out.println(list.get(1));
}
}

for循环遍历ArrayList
循环存储元素的值
public class ArrayListTest {
@Test
public void test03(){
List list = new ArrayList();
for (int i = 0; i < 20; i++){
list.add("张三" + i);
}
System.out.println(list.size());
for (int i = 0; i < list.size(); i++){
System.out.print(list.get(i));
}
}
}
获取存储的元素个数及遍历后每个元素的值
20
张三0张三1张三2张三3张三4张三5张三6张三7张三8张三9张三10张三11张三12张三13张三14张三15张三16张三17张三18张三19
foreach循环遍历ArrayList
foreach循环遍历的数组为增强版的for循环

public class ArrayListTest {
@Test
public void test06(){
List list = new ArrayList();
for (int i = 0; i < 10; i++){
list.add("张三" + i);
}
for (int i = 0; i < list.size(); i++){
System.out.print(list.get(i) + "\t");
}
System.out.println();
// Object 集合中元素的数据类型
// name 遍历后集合中每一个元素的变量
// list 被遍历的集合
for (Object name : list){
System.out.print(name + "\t");
}
}
}
张三0 张三1 张三2 张三3 张三4 张三5 张三6 张三7 张三8 张三9
张三0 张三1 张三2 张三3 张三4 张三5 张三6 张三7 张三8 张三9
ArrayList插入数据
在数组指定位置上添加新元素使用list.add(int dext,Object element)

public class ArrayListTest {
@Test
public void test(){
List list = new ArrayList();
for (int i = 0; i < 10; i++){
list.add("张三" + i);
}
System.out.println(list);
list.add(4,"李四");
System.out.println(list);
}
}
获取原来元素数组和添加新元素后的新数组
[张三0, 张三1, 张三2, 张三3, 张三4, 张三5, 张三6, 张三7, 张三8, 张三9]
[张三0, 张三1, 张三2, 张三3, 李四, 张三4, 张三5, 张三6, 张三7, 张三8, 张三9]
ArrayList删除数据
将数组指定位置上的元素删除使用list.remove(int dext)
public class ArrayListTest {
@Test
public void test04(){
List list = new ArrayList();
for (int i = 0; i < 10; i++){
list.add("张三" + i);
}
System.out.println(list);
list.remove(5);
System.out.println(list);
}
}
获取原来元素数组和删除指定元素后的新数组
[张三0, 张三1, 张三2, 张三3, 张三4, 张三5, 张三6, 张三7, 张三8, 张三9]
[张三0, 张三1, 张三2, 张三3, 张三4, 张三6, 张三7, 张三8, 张三9]
ArrayList修改数据
将数组指定位置上的元素删除使用list.set(int index, Object element)

public class ArrayListTest {
@Test
public void test05(){
List list = new ArrayList();
for (int i = 0; i < 10; i++){
list.add("张三" + i);
}
System.out.println(list);
list.set(5,"李四");
System.out.println(list);
}
}
获取原来元素数组和修改指定元素后的新数组
[张三0, 张三1, 张三2, 张三3, 张三4, 张三5, 张三6, 张三7, 张三8, 张三9]
[张三0, 张三1, 张三2, 张三3, 张三4, 李四, 张三6, 张三7, 张三8, 张三9]
泛型
泛型在此处可以简单理解为参数的数据类型(限定你存储的数据类型)
注意:低版本中除了在接口处添加泛型的同时也要在实例化对象后面添加泛型

public class ArrayListTest {
@Test
public void test07(){
// 泛型 可以简单理解为参数的数据类型
List<String> list = new ArrayList();
for (int i = 0; i < 10; i++){
list.add("张三" + i);
}
for (String name : list){
System.out.print(name + "\t");
}
}
}
输出
张三0 张三1 张三2 张三3 张三4 张三5 张三6 张三7 张三8 张三9
迭代器遍历集合
用途:遍历集合时为了提高效率
使用list.listIterator()方法

listIterator方法在底层源代码中继承成了Iterator
Iterator是一个接口

所以直接使用Iterator接口引用
迭代器遍历使用while循环中的hasNext()方法
public class ArrayListTest {
@Test
public void test08(){
List<String> list = new ArrayList();
for (int i = 0; i < 10; i++){
list.add("张三" + i);
}
// 获取该集合的迭代器
Iterator<String> it = list.listIterator();
while (it.hasNext()){
String next = it.next();
System.out.print(next + "\t");
}
}
}
获取数据
张三0 张三1 张三2 张三3 张三4 张三5 张三6 张三7 张三8 张三9
迭代器遍历后的数据不能重复迭代(游标只能向上不能向下)
public class ArrayListTest {
@Test
public void test08(){
List<String> list = new ArrayList();
for (int i = 0; i < 10; i++){
list.add("张三" + i);
}
// 获取该集合的迭代器
Iterator<String> it = list.listIterator();
while (it.hasNext()){
String next = it.next();
System.out.print(next + "\t");
}
System.out.println();
System.out.println("+++++++++++++++");
while (it.hasNext()){
String next = it.next();
System.out.print(next + "\t");
}
System.out.println("+++++++++++++++");
}
}
输出
张三0 张三1 张三2 张三3 张三4 张三5 张三6 张三7 张三8 张三9
+++++++++++++++
+++++++++++++++
迭代器优点:
- 遍历速度快
迭代器缺点: - 迭代器遍历后的数据不能重复迭代
LinkedList
在ArrayList源代码中 ArrayList实现了接口List
List接口中有很多实现类
最常用的有ArrayList和LinkedList

所以ArrayList里的方法都可以使用LinkedList去实现
ArrayList与LinkedList
数据结构不同
- ArrayList底层源代码是Object[]数组结构
- LinkedList底层源代码是一个双向链表结构
使用业务场景不同
- ArrayList新增和删除数据速度慢(因为底层的数组结构在存储数据时可能会发生数组的拷贝,删除数据时会发生数据的移动,除非删除的是最后一位 ); 查询速度快(因为底层是数组,一个线型表数组是有下标的,下标是连续的)。
- LinkedList新增和删除数据速度快(因为底层的双向链表结构 ,在删除或新增数据时本身数据不用动 ,只需要更改指针的指向) 查询速度慢(因为底层是链表所以在查询的时候要对下标重新排序)
ArrayList

LinkedList

Set与List区别
- Set 接口实例存储的是无序的,不重复的数据。List 接口实例存储的是有序的,可以重复的元素。
- Set检索效率低下,删除和插入效率高,插入和删除不会引起元素位置改变 <实现类有HashSet,TreeSet>。
- List和数组类似,可以动态增长,根据实际存储的数据的长度自动增长List的长度。查找元素效率高,插入删除效率低,因为会引起其他元素位置改变 <实现类有ArrayList,LinkedList,Vector> 。
List:有序可重复 有序指的是按照新增的顺序存储 可重复指的是存储元素的值可以重复

Set:无序不可重复 无序指的是不会按照新增的顺序存储 不可重复指的是存储元素的值不可以重复

HashSet底层源代码中继承了抽象的AbstractSet 实现了接口Set

迭代器与foreach两种方式遍历Set
foreach方式遍历Set
public class HashSetTest {
@Test
public void test03(){
Set<String> set = new HashSet();
for (int i = 0; i < 10; i++){
set.add("张三" + i);
}
System.out.println(set);
for (String name : set) {
System.out.print(name);
}
}
}
输出
[张三7, 张三8, 张三5, 张三6, 张三3, 张三4, 张三1, 张三2, 张三0, 张三9]
张三7 张三8 张三5 张三6 张三3 张三4 张三1 张三2 张三0 张三9
迭代器方式遍历Set
public class HashSetTest {
@Test
public void test04(){
Set<String> set = new HashSet();
for (int i = 0; i < 10; i++){
set.add("张三" + i);
}
System.out.println(set);
Iterator<String> it = set.iterator();
while (it.hasNext()){
String name = it.next();
System.out.print(name);
}
}
}
输出
[张三7, 张三8, 张三5, 张三6, 张三3, 张三4, 张三1, 张三2, 张三0, 张三9]
张三7 张三8 张三5 张三6 张三3 张三4 张三1 张三2 张三0 张三9
注:推荐使用迭代器方式遍历Set
LinkedHashSet
LinkedHashSet:有序不可重复 有序指的是按照新增的顺序存储

LinkedHashSet底层源代码中继承了HashSet

TreeSet
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Book implements Comparable{
/**
* 书名
*/
private String name;
/**
* 作者
*/
private String author;
/**
* 单价
*/
private int price;
/**
* 销量
*/
private int sales;
@Override
public int compareTo(Object o) {
Book book = (Book) o;
int x = this.author.compareTo(book.getAuthor());
int y = this.price - book.getPrice();
int z = book.getSales() - this.sales;
int k = this.name.compareTo(book.name);
if (x != 0) {
return x;
}else if (y != 0){
return -y;
}else if (z !=0){
return z;
}else {
return k;
}
}
}
public class TreeSetTest {
@Test
public void test01(){
SortedSet<Book> books = new TreeSet<>();
books.add(new Book("一步之遥","姜文",35,180));
books.add(new Book("浮成谜事","娄烨",35,150));
books.add(new Book("邪不压正","姜文",35,150));
books.add(new Book("推拿","娄烨",33,150));
books.add(new Book("让子弹飞","姜文",33,150));
books.add(new Book("颐和园","娄烨",35,180));
books.add(new Book("一步之遥","姜文",35,180));
Iterator<Book> it = books.iterator();
while (it.hasNext()){
Book book = it.next();
System.out.println(book);
}
}
}
输出
Book(name=一步之遥, author=姜文, price=35, sales=180)
Book(name=邪不压正, author=姜文, price=35, sales=150)
Book(name=让子弹飞, author=姜文, price=33, sales=150)
Book(name=颐和园, author=娄烨, price=35, sales=180)
Book(name=浮成谜事, author=娄烨, price=35, sales=150)
Book(name=推拿, author=娄烨, price=33, sales=150)
双列集合Map
HashMap存储与取值
HashMap是一个keyValue结构
Map存储内容使用put方法
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Person {
/**
* 姓名
*/
private String nickname;
/**
* 身份证号
*/
private String idCard;
/**
* 手机号
*/
private String mobile;
}
public class HashMapTest {
@Test
public void test(){
Map<String, Person> map = new HashMap<>();
ChineseNameGenerator chineseNameGenerator = ChineseNameGenerator.getInstance();
GenericGenerator chineseIDCardNumberGenerator = ChineseIDCardNumberGenerator.getInstance();
ChineseMobileNumberGenerator chineseMobileNumberGenerator = ChineseMobileNumberGenerator.getInstance();
String mobile01 = chineseMobileNumberGenerator.generate();
map.put(mobile01,new Person(chineseNameGenerator.generate(),chineseIDCardNumberGenerator.generate(),mobile01));
String mobile02 = chineseMobileNumberGenerator.generate();
map.put(mobile02,new Person(chineseNameGenerator.generate(),chineseIDCardNumberGenerator.generate(),mobile02));
String mobile03 = chineseMobileNumberGenerator.generate();
map.put(mobile03,new Person(chineseNameGenerator.generate(),chineseIDCardNumberGenerator.generate(),mobile03));
Person person01 = map.get(mobile01);
Person person02 = map.get(mobile02);
Person person03 = map.get(mobile03);
System.out.println(person01);
System.out.println(person02);
System.out.println(person03);
}
}
获取存储的值
Person(nickname=丁脖阁, idCard=422548199903257166, mobile=18312990221)
Person(nickname=张女僵, idCard=452994198611109859, mobile=13457274572)
Person(nickname=史凸叉, idCard=454919199508301785, mobile=18402037045)
HashMap修改和删除value值
HashMap修改value值还是使用put方法
put 方法key如果不存在就是新增 存在就是修改
Map 的key无序不可重复 value值可以重复
public class HashMapTest {
@Test
public void test03() {
Map<String, String> map = new HashMap<>();
map.put("key01","value01");
map.put("key02","value02");
map.put("key03","value03");
System.out.println("key01 >>> " + map.get("key01"));
map.put("key01","v1");
System.out.println("key01 >>> " + map.get("key01"));
}
}
输出
key01 >>> value01
key01 >>> v1
HashMap删除value值使用remove方法
public class HashMapTest {
@Test
public void test04() {
Map<String, String> map = new HashMap<>();
map.put("key01","value01");
map.put("key02","value02");
map.put("key03","value03");
System.out.println("key01 >>> " + map.get("key01"));
map.remove("key01");
System.out.println("key01 >>> " + map.get("key01"));
}
}
输出
key01 >>> value01
key01 >>> null
HashMap判断key是否存在_HashMap获取的值不存在返回默认值
方式一:使用if判断中containsKey方法
public class HashMapTest {
@Test
public void test05() {
Map<String, String> map = new HashMap<>();
map.put("key01","value01");
map.put("key02","value02");
map.put("key03","value03");
System.out.println("key01 >>> " + map.get("key01"));
if (map.containsKey("key01")){
map.remove("key01");
System.out.println("key05 >>> " "删除key05");
}
System.out.println("key01 >>> " + map.get("key01"));
}
}
输出
key01 >>> value01
key05 >>> 删除key05
key01 >>> null
方式二:map.getOrDefault方法
public class HashMapTest {
@Test
public void test06() {
Map<String, String> map = new HashMap<>();
map.put("key01","value01");
map.put("key02","value02");
map.put("key03","value03");
System.out.println("key01 >>> " + map.getOrDefault("key01","value01"));
System.out.println("key05 >>> " + map.getOrDefault("key05","删除key05"));
}
}
输出
key01 >>> value01
key05 >>> 删除key05
HashMap根据key遍历
先使用map.keySet方法然后使用迭代器方式拿到key的值,
public class HashMapTest {
@Test
public void test07() {
Map<String, String> map = new HashMap<>();
for (int i = 0; i < 10; i++) {
map.put("key" + i,"value" + i);
}
Set<String> keySet = map.keySet();
Iterator<String> it = keySet.iterator();
while (it.hasNext()){
String key = it.next();
System.out.println("key >>> " + key + "\tvalue >>> " + map.get(key));
}
}
}
输出
key >>> key1 value >>> value1
key >>> key2 value >>> value2
key >>> key0 value >>> value0
key >>> key5 value >>> value5
key >>> key6 value >>> value6
key >>> key3 value >>> value3
key >>> key4 value >>> value4
key >>> key9 value >>> value9
key >>> key7 value >>> value7
key >>> key8 value >>> value8
HashMap遍历value值
使用map.values方法(map.values方法返回的是一个集合Collection)拿到迭代器

然后使用迭代器的方式遍历value值
public class HashMapTest {
@Test
public void test09() {
Map<String, String> map = new HashMap<>();
for (int i = 0; i < 10; i++) {
map.put("key" + i,"value" + i);
}
Collection<String> values = map.values();
Iterator<String> it = values.iterator();
while (it.hasNext()){
String value = it.next();
System.out.print(value + "\t");
}
}
}
获取value值输出
value1 value2 value0 value5 value6 value3 value4 value9 value7 value8
使用entrySet遍历HashMap
把key和Value值看作是一个整体使用map.entrySet方法(map.entrySet方法返回的就是key和Value)

然后使用迭代器的方式遍历HashMap
public class HashMapTest {
@Test
public void test10() {
Map<String, String> map = new HashMap<>();
for (int i = 0; i < 10; i++) {
map.put("key" + i,"value" + i);
}
Set<Map.Entry<String, String>> entrySet = map.entrySet();
Iterator<Map.Entry<String, String>> it = entrySet.iterator();
while (it.hasNext()){
Map.Entry<String, String> entry = it.next();
System.out.println("key >>> " + entry.getKey() + "\tvalue >>> " + entry.getValue());
}
}
}
直接获取到key和Value值
key >>> key1 value >>> value1
key >>> key2 value >>> value2
key >>> key0 value >>> value0
key >>> key5 value >>> value5
key >>> key6 value >>> value6
key >>> key3 value >>> value3
key >>> key4 value >>> value4
key >>> key9 value >>> value9
key >>> key7 value >>> value7
key >>> key8 value >>> value8
LinkedHashMap
LinkedHashMap在底层源代码中继承了HashMap

LinkedHashMap:有序不可重复 有序指的是按照新增的顺序存储
public class LinkedHashMapTest {
@Test
public void test(){
Map<String, String> map = new LinkedHashMap<>();
for (int i = 0; i < 10; i++) {
map.put("key" + i,"value" + i);
}
Set<Map.Entry<String, String>> entrySet = map.entrySet();
Iterator<Map.Entry<String, String>> it = entrySet.iterator();
while (it.hasNext()){
Map.Entry<String, String> entry = it.next();
System.out.println("key >>> " + entry.getKey() + "\tvalue >>> " + entry.getValue());
}
}
}
输出
key >>> key0 value >>> value0
key >>> key1 value >>> value1
key >>> key2 value >>> value2
key >>> key3 value >>> value3
key >>> key4 value >>> value4
key >>> key5 value >>> value5
key >>> key6 value >>> value6
key >>> key7 value >>> value7
key >>> key8 value >>> value8
key >>> key9 value >>> value9
ConcurrentHashMap_Hashtable
Hashtable 无序不可重复的
public class HashtableTest {
@Test
public void test(){
Map<String, String> map = new Hashtable<>();
for (int i = 0; i < 10; i++) {
map.put("key" + i,"value" + i);
}
Set<Map.Entry<String, String>> entrySet = map.entrySet();
Iterator<Map.Entry<String, String>> it = entrySet.iterator();
while (it.hasNext()){
Map.Entry<String, String> entry = it.next();
System.out.println("key >>> " + entry.getKey() + "\tvalue >>> " + entry.getValue());
}
}
}
输出
key >>> key9 value >>> value9
key >>> key8 value >>> value8
key >>> key7 value >>> value7
key >>> key6 value >>> value6
key >>> key5 value >>> value5
key >>> key4 value >>> value4
key >>> key3 value >>> value3
key >>> key2 value >>> value2
key >>> key1 value >>> value1
key >>> key0 value >>> value0
ConcurrentHashMap
public class ConcurrentHashMapTest {
@Test
public void test(){
Map<String, String> map = new ConcurrentHashMap<>();
for (int i = 0; i < 10; i++) {
map.put("key" + i,"value" + i);
}
Set<Map.Entry<String, String>> entrySet = map.entrySet();
Iterator<Map.Entry<String, String>> it = entrySet.iterator();
while (it.hasNext()){
Map.Entry<String, String> entry = it.next();
System.out.println("key >>> " + entry.getKey() + "\tvalue >>> " + entry.getValue());
}
}
}
输出
key >>> key1 value >>> value1
key >>> key2 value >>> value2
key >>> key0 value >>> value0
key >>> key5 value >>> value5
key >>> key6 value >>> value6
key >>> key3 value >>> value3
key >>> key4 value >>> value4
key >>> key9 value >>> value9
key >>> key7 value >>> value7
key >>> key8 value >>> value8
903

被折叠的 条评论
为什么被折叠?



