Map实现类结构情况---知识点(部分)
一:Map实现类结构情况
- Map 双列数据 用于存储key-value对的数据 ----类似于高中讲的函数 y=f(x)
-
--HashMap: 子类 --LinkedHashMap:
-
-- TreeMap:
-
--Hashtable: 子类 --Properties:
区别
1.HashMap:作为我们的主要实现类,线程是不安全的,所以效率很高,可以存放null的key和value
2.Hashtable:作为我们古老的实现类 在1.2时候才有,线程是安全的,所以效率很低 是不能存放key和value的
public class MapTest {
@Test
public void test1(){
// Map map = new HashMap();
Hashtable map = new Hashtable();
map.put(null,123);
map.put(null,null);
System.out.println();
}
}
3.LinkedHashMap:能够保证在遍历的时候 是按照添加的顺序进行输出的,原因是:在原有的HashMap底层的基础上,添加了一对指针
指向前一个元素,对于频繁的进行遍历操作,我们当前的LinkedHashMap要高于我们的HashMap。
4.TreeMap:可以按照添加的key-value进行排序,实现排序的遍历 此时考虑key的自然排序,或者定制排序。底层使用对的是红黑树
注意:HashMap底层:数据+链表,仅限(jdk1.7之前)在(jdk8中) 是数组+链表+红黑树
5.Properties :常用来处理配置文件 key和value都是String 类型
面试题:
HashMap 的底层原理:
HashMap 和 Hashtable 的区别
CurrentHashMap 和Hashtable 异同(暂时不说)
二:Map结构的理解
- Map中是无序的,不可以重复的,使用set进行存放所有的key,---->要求我们所在的类要重写equals()和hashCode()方法(依HashMap举例)
- Map中的value是无序的,可以重复的,使用Collection存放所有的value,所在的类要重写equals()方法
- 一个键值对构成了一个Entry对象
- Map中的entry:无序的,不可以重复的,使用set存放所有的entry
HashMap 的底层实现原理
- 以jdk7为例
HashMap map = new HashMap();
- 在实例化的时候底层创建了一个长度是16的一维数组,Entry[] table
...可能已经执行多次的put()方法了
map.put(key1,value1)往里面添加数据 <br>
- 1.首先先调用key1所在类的hashCode()方法,计算key1的哈希值,此哈希值经过某种算法之后 得到Entry数组中存放的位置
- 2.如果此位置上数据为空,此时key1-value1添加成功 ---情况一
- 3.如果此位置上数据不为空,(意味着此位置上存在一个或者多个数据(已链表的形式存在) 比较key1和已经存在的一个或者多个数据的哈希值
- 如果key1的哈希值和已经存在的hash数值都不同,此时的key1-value1添加成功----情况二
- 如果key1的哈希值和已经存在的某个数据(key2-value2)哈希值相同,继续比较,调用key1所在类中equals(key2)方法,比较
- 有两种情况
- 1.如果equals()返回的是false 则证明添加成功---情况三
- 2.如果equals()返回的是true 使用value1替换value2
说明:情况二和情况三 此时的key1-value1和原来的数据以链表的方式存储,再添加的时候会涉及的扩容问题,扩容原来的2倍,并将原来的复制过来
- 在jdk8中相对于jdk7中的不同
- 1.底层没有长度为16的数组
- 2.jdk8中底层的数组是Node[] 而非 Entry[]数组
- 3.首次调用put方法时候底层会创建长度为16的数组
- 4.jdk7中只有数组+链表 在jdk8中;数组+链表+红黑树
- 当数组某一个索引的位置上面的元素以链表形式的存在的数据个数>8 且当前数组的长度>64的时候,此时索引上的数组改为使用红黑树进行存放
Map的常用方法:
添加
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
public class MapTest {
// 添加
@Test
public void test1(){
Map map = new HashMap();
map.put("AA",123);
map.put(545,123);
map.put("BB",123);
System.out.println(map);
}
}
@Test
public void test2(){
Map map = new HashMap();
map.put("AA",123);
map.put("BB",123);
Map map1 = new HashMap();
map.put("CC",123);
map.put("DD",123);
map.putAll(map1);
System.out.println(map);
}
删除
@Test
public void test3(){
Map map = new HashMap();
map.put("AA",123);
map.put("BB",123);
map.put("CC",123);
map.put("DD",123);
map.remove("DD");
System.out.println(map);
}
//没有的话返回值就是null
清空数据
@Test
public void test4() {
Map map = new HashMap();
map.put("AA", 123);
map.put("BB", 123);
map.put("CC", 123);
map.put("DD", 123);
map.clear();
System.out.println(map);
}
//调用map.size()方法不会出现空指针异常,结果是0
查询指定元素
//元素查询
@Test
public void test5() {
Map map = new HashMap();
map.put("AA", 123);
map.put("BB", 123);
map.put("CC", 123);
map.put("DD", 123);
System.out.println(map.get(45));
}
判断当前的map是否包含当前的key或者value
@Test
public void test6() {
Map map = new HashMap();
map.put("AA", 123);
map.put("BB", 123);
map.put("CC", 123);
map.put("DD", 123);
boolean isExist = map.containsKey("BB");
System.out.println(isExist);
}
是否包含指定的value方法
@Test
public void test7() {
Map map = new HashMap();
map.put("AA", 123);
map.put("BB",789);
map.put("CC", 456);
map.put("DD", 123);
boolean isExist= map.containsValue(123);
System.out.println(isExist);
}
元视图操作方法
- 遍历所有的Key方法
@Test
public void test8() {
Map map = new HashMap();
map.put("AA", 123);
map.put("BB", 789);
map.put("CC", 456);
map.put("DD", 123);
//遍历所有的key
Set set = map.keySet();
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
遍历所有的value
@Test
public void test9() {
Map map = new HashMap();
map.put("AA", 123);
map.put("BB", 789);
map.put("CC", 456);
map.put("DD", 123);
//遍历所有的key
Collection values = map.values();
Iterator iterator = values.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
遍历所有的key-value
@Test
public void test1_1() {
Map map = new HashMap();
map.put("AA", 123);
map.put("BB", 789);
map.put("CC", 456);
map.put("DD", 123);
Set set = map.entrySet();
for (Object o : set) {
System.out.println(o);
}
}
TreeMap两种添加方式的使用
向TreeMap中添加key-value 要求key必须是由同一个类创建的对象,因为我们要按照key进行排序,不能按照Value进行排序,排序方式:自然排序,定制排序(使用Comparator然后按照想要的进行排序)
//自然排序
@Test
public void test1(){
TreeMap map = new TreeMap();
map.put("AA",123);
map.put("BB",345);
map.put("EE",567);
Set set = map.entrySet();
Iterator iterator = set.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
Properties说明
import org.junit.Test;
import java.io.FileInputStream;
import java.util.Properties;
public class PropertiesTest {
@Test
public void test() throws Exception {
Properties properties = new Properties();
//进行读取
FileInputStream is = new FileInputStream("jdbc.properties");
properties.load(is);
// properties.load(is);//加载流对应的文件
//读取配置文件
String name = properties.getProperty("name");
String password = properties.getProperty("password");
System.out.println("姓名:"+name+"----密码:"+password);
}
}
Collections工具类的使用
Collections:操作Collection,Map的工具类
面试题Collections和Collection的区别:
- Collection 是一个集合接口。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式。
- Collections 是一个包装类。它包含有各种有关集合操作的静态多态方法。此类不能实例化,就像一个工具类,服务于Java的Collection框架。
- Collections 是一个包装类,Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许,一些 collection 是有序的,而另一些则是无序的。
常用方法
- 反转
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CollectionTest {
@Test
public void test() {
//进行反转
List list = new ArrayList();
list.add(123);
list.add(433);
list.add(235);
list.add(876);
System.out.println(list);
Collections.reverse(list);
System.out.println(list);
}
}
- 随机化输出
@Test
public void test1() {
//随机化输出
List list = new ArrayList();
list.add(123);
list.add(433);
list.add(235);
list.add(876);
System.out.println(list);
Collections.shuffle(list);
System.out.println(list);
}
- 自然排序
@Test
public void test2() {
//自然排序
List list = new ArrayList();
list.add(123);
list.add(433);
list.add(235);
list.add(876);
System.out.println(list);
Collections.sort(list);
System.out.println(list);
}
- 交换索引位置上的元素
@Test
public void test3() {
//交换索引位置上的元素
List list = new ArrayList();
list.add(123);
list.add(433);
list.add(235);
list.add(876);
System.out.println(list);
Collections.swap(list,1,2);
System.out.println(list);
}
- 返回指定集合中指定元素的出现次数
@Test
public void test4() {
//交换索引位置上的元素
List list = new ArrayList();
list.add(123);
list.add(433);
list.add(235);
list.add(235);
list.add(876);
System.out.println(list);
Collections.frequency(list,235);
System.out.println(list);
}
- 将src中的内容复制到dest中
@Test
public void test5() {
//复制
List list = new ArrayList();
list.add(123);
list.add(433);
list.add(235);
list.add(235);
list.add(876);
// System.out.println(list);
// List dest = new ArrayList();
// dest.add(3232);
// dest.add(3232);
// dest.add(3232);
// dest.add(3232);
// dest.add(3232);
List dest = Arrays.asList(new Object[list.size()]);
Collections.copy(dest,list);
System.out.println(dest);
}