Java集合二(Map和泛型)

Map集合和泛型

Map

什么是Map?

接口Map:将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值

HashMap

健值对:一个健对应一个值

无序排列:添加顺序和输出顺序不一致

特点:

​ 健值对形式存在 任意类型

​ 允许Key和Value都为null

​ 健不能重复 如果健重复,里面的值会被新值覆盖掉

​ 线程不安全,效率高

遍历方式:注意!HashMap自身是无法用for和foreach遍历的

​ 1.调用Keyset方法,得到set集合,再进行遍历

​ 2.调用entryset方法,得到键值对的集合

面试题:底层原理

jdk1.7:

​ HashMap的底层基于数组+链表实现,用键值对的形式存储数据

根据key的hashcode元素得到一个int值,确定该键值对放在数组的哪个位置

key值hash运算后得到的索引位置相同的时候,称为hash碰撞,会以链表的形式放在后面

链表长度过长,导致取值的时候效率太低

jdk1.8:

​ HashMap的底层基于数组+链表+红黑树(一种倾向于自平衡的二叉树)

Demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.ifueen.classwork.hashmap;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class HashMapTest1 {
/*
* HashMap Demo
* */
public static void main(String[] args) {
// TODO Auto-generated method stub
HashMap map = new HashMap();
map.put("三十二", "南京");
map.put("人民北路", "没有人民");
System.out.println(map);
HashMap map1 = new HashMap();
map1.put("想要", "翅膀");
map1.put("想要", "旧金山");
System.out.println(map1);

//遍历
//调用keyset方法
Set set = map.keySet(); //返回此映射中所包含的键的 Set 视图
for (Object object : set) {
System.out.println(object+""+map.get(object));
}
//迭代器
Set set1 = map1.keySet(); //返回此映射中所包含的键的 Set 视图
Iterator iterator = set1.iterator();
while (iterator.hasNext()) {
Object object = (Object) iterator.next();
System.out.println(object+""+map1.get(object));
}

}

}

HashTable

特点:

​ 健和值都不能为null

​ 线程安全 put方法是同步方法

​ 健值不能重复 重复会导致原来的值被覆盖掉

Demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.ifueen.classwork.hashtable;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;

public class HashtableTest {
/*
* Hashtable
* */
public static void main(String[] args) {
// TODO Auto-generated method stub
Hashtable hashtable = new Hashtable(); //新建对象
hashtable.put(1, "我们"); //调用put方法传入健值
hashtable.put(2, "不能");
hashtable.put(3, "失去");
hashtable.put(4, "信仰");
//hashtable.put(); //不允许key或者value值为空
System.out.println(hashtable); //输出的结果是无序的

//遍历
//通过Set来遍历
Set set = hashtable.entrySet(); //得到Set对象
Iterator iterator = set.iterator(); //得到迭代器
while (iterator.hasNext()) {
Object object = (Object) iterator.next(); //类型强转
System.out.println(object); //输出
}


Collection collection = hashtable.values(); //创建Collection类的对象
//foreach遍历
for (Object object : collection) {
System.out.println(object);
}
//迭代器
Iterator iterator2 = collection.iterator();
while (iterator2.hasNext()) {
Object object = (Object) iterator2.next();
System.out.println(object); //输出
}
}

}

ConcurrentHashMap

特点:

​ 线程安全 在put方法里面同步了核心代码块

​ key和value值都不能为null

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.ifueen.classwork.concurrenthashmaptest;

import java.util.concurrent.ConcurrentHashMap;

public class ConcurrentHashMapTest {
/*
* ConcurrentHashMap
* */
public static void main(String[] args) {
// TODO Auto-generated method stub
ConcurrentHashMap cumap = new ConcurrentHashMap();
cumap.put("1", "你好哇");
cumap.put("2", "李银河");
//cumap.put(null,null); //key或者value不能为空
System.out.println(cumap);
}

}

面试题:区别

相同点:

​ 都是Map接口的实现类

​ 都是键值对来进行存储,任意类型任意多个数据

不同点:

​ HashMap线程不安全,可以用null作为key或value 效率较高

​ HashTable同步方法,线程安全,不能用null作为key或value 效率较低

​ ConcurrentHashMap同步代码块,线程安全,不能用null作为key或value 效率较HashTable高一些

Collections工具类

专门用来对集合进行操作的工具类,方法很多,可以实现不同的功能,详情请见API文档

Properties读写文件

是Hashtable的子类,在用自己的存入方法时只能够传入String类型的数据

key和value里面的值都不能为null

持久化:

​ 内存到磁盘

​ 磁盘到内存

路径:

​ 相对路径:项目的根路径

​ 绝对路径:指定位置

泛型

泛指的一种类型

用来约束容器只能存放某种类型的数据

泛型的上限和下限

上限:约束传入的类型最高为什么类型

语法:? extends 类型

下限:约束传入的类型最低为什么类型

语法:? super 类型

Demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.ifueen.classwork.generic;

import java.util.ArrayList;
import java.util.List;

public class FanxTest {
/*
* 泛型:规定了容器只能存放某种类型的数据
* */
public static void main(String[] args) {
// TODO Auto-generated method stub
ArrayList<MyObject> list = new ArrayList<MyObject>();
//list.add("可不可以呢"); //只能传入泛型规定的类型
list.add(new MyObject("当然是可以的辣"));
System.out.println(list);

//泛型的上限 约束了传入的类型 最高为什么类型 语法:? extends 类型
//top(list); //编译报错,因为MyObject上限不为Number
ArrayList<MyObject2> list2 = new ArrayList<MyObject2>();
list2.add(new MyObject2("深井冰"));
top(list2); //MyObject2的继承了Number 所以可以放进去
System.out.println(list2);
//泛型的下限 约束了传入的类型最低为什么类型 语法:? super 类型

ArrayList<Number> list3 = new ArrayList<Number>();
list3.add(456);
//bottom(list); //编译报错,MyObject2的类型不再MyObject之下
bottom(list3);
System.out.println(list3);
}

public static void top(List<? extends Number> list){}
public static void bottom(List<? super MyObject2> list){}

}

MyObject类

1
2
3
4
5
6
7
8
9
10
11
12
package com.ifueen.classwork.generic;
public class MyObject {
String name;
public MyObject(String name) {
super();
this.name = name;
}
@Override
public String toString() {
return "MyObject [name=" + name + "]";
}
}

MyObject2类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.ifueen.classwork.generic;

public class MyObject2 extends Number{
String name;

public MyObject2(String name) {
super();
this.name = name;
}
@Override
public String toString() {
return "MyObject [name=" + name + "]";
}
@Override
public int intValue() {
// TODO Auto-generated method stub
return 0;
}
@Override
public long longValue() {
// TODO Auto-generated method stub
return 0;
}
@Override
public float floatValue() {
// TODO Auto-generated method stub
return 0;
}
@Override
public double doubleValue() {
// TODO Auto-generated method stub
return 0;
}
}
❤赏点钱让我买杯快乐水8❤