package com.atguigu.java;
import org.junit.Test;
import java.util.*;
/**
* 一、Map实现类的结构:
* |----Map:双列数据,存储具有key-value对的数据,类似于高中时的函数。
* |----HashMap:作为Map的主要实现类。线程不安全,效率低。可以存储null的key,value
* |----LinkedHashMap:能够保证在遍历Map元素时,可以按照添加的顺序实现遍历。
* 原因:在原有的HashMap底层结构的基础上,添加了一对指针,指向了前一个和后一个元素。
* 对于频繁的遍历操作,此类的执行效率要高于HashMap。
*
* |----TreeMap:保证按照添加的key-value对进行排序,实现排序遍历。此时使用key进行排序,自然排序或者定制排序。
* 底层使用的是红黑树。
*
* |----Hashtable:作为古老的实现类。线程安全,效率低。不可以存储null的key,value
* |----Properties:常用来处理配置文件。key和value都是String类型。
*
* HashMap的底层:数组+链表(jdk7及之前)
* 数组+链表+红黑树(jdk8及之后)
* 面试题:
* 1.HashMap的底层实现原理?
* 2.HashMap和Hashtable的异同?
* 3.CurrentHashMap和Hashtable的异同?(暂时不讲)
*
*
* 二、Map结构的理解:
* Map中的key是无序的并不可重复的,使用Set储存所有的key----重写hashCode()和equals()方法。(以hashMap为例)
* Map中的value:无序的并可重复的,使用Collection储存所有的value-----重写equals()方法
* 一个键值对:key-value构成一个Entry对象。
* Map中的entry:无序的并不可重复的,使用Set存储所有的entry
*
* 三、HashMap的底层实现原理?
*
* HashMap的底层:数组+链表(jdk7及之前)
* 数组+链表+红黑树(jdk8及之后)
*
* 以JDK7.0为例说明:
*
* HashMap map = new HashMap();
* 底层在实例化以后,底层创建了长度为 16 的一维数组Entry[] table。
* ....可能已经执行过多次put....
* map.put(key1,value1):方法计算key1的哈希值
* 首先调用key1所在类的hashCode(),此哈希值经过某种算法计算以后,得到在Entry数组中的存放位置。
* 如果此位置上的数据为空,此时的key1 value1直接添加成功。----情况1
* 如果此位置上的数据不为空,(意味着此位置上存在一个或者多个数据(以链表形式存在)),比较当前的key1和已经存在的一个或多个数据的哈希值,
* 如果key1的哈希值与已经存在的数据的哈希值都不相同,此时key1-value1就能够添加成功。----情况2
* 如果key1的哈希值和已经存在的某一个数据(key2-value2)的key2的哈希值相同,继续比较:调用key1所在类的equals()方法:
* 比较:
* 如果返回的是false:此时key1-value1就能够添加成功。----情况3
* 如果返回的是true:使用value1去替换key2的value2值。
*
* 补充:关于情况2和情况3:此时key1-value1和原来的数据以链表的方式存储。
*
* 在不断的添加过程中,会涉及到扩容的问题,当超出临界值(且要存放的位置非空)时,默认的扩容方式L:扩容为原来容量的2倍,并将原来的数据复制过来。
*
* JDK8.0相较于JDK7.0在底层实现的不同:
* 1. new HashMap():底层没有创建一个长度为16的数组
* 2.JDK8.0底层的数组是:Node[],而非Entry[]
* 3.首次调用put()方法时,底层才创建长度为16的数组。
* 4.JDK7.0的底层结构只有:数组+链表。JDK8.0中底层结构:数组+链表+红黑树。
* 4.1形成链表时,七上八下,jdk7:新元素在上指向旧元素;jdk8:旧元素在上指向新元素
* 当数组的某一个索引位置上的元素以链表的形式存在的数据个数>8 且当前数组的长度>64时,
* 此时此索引位置上的所有数据改为使用红黑树存储。
*
* DEFAULT_INITIAL_CAPACITY : HashMap的默认容量,16
* DEFAULT_LOAD_FACTOR:HashMap的默认加载因子:0.75
* threshold:扩容的临界值,=容量*填充因子---16 * 0.75 = 12
* TREEIFY_THRESHOLD:Bucket中链表长度大于该默认值,转化为红黑树:8
* MIN_TREEIFY_CAPACITY:桶中的Node被树化时最小的hash表容量:64
*
*
* 四、LinkedHashMap的底层实现原理?
* LinkedHashMap的底层使用的结构和HashMap相同,因为LinkedHashMap继承于HashMap类
* 区别就在于:LinkedHashMap内部提供了Entry,替换了HashMap的Node.
* 多了一个before和after
*
*
* static class Entry<K,V> extends HashMap.Node<K,V> {
Entry<K,V> before, after;//能够记录添加元素的先后顺序
Entry(int hash, K key, V value, Node<K,V> next) {
super(hash, key, value, next);
}
}
*五、Map接口 中定义的方法:
添加、删除、修改操作:
Object put(Object key,Object value):将指定key-value添加到(或修改)当前map对象中
void putAll(Map m):将m中的所有key-value对存放到当前map中
Object remove(Object key):移除指定key的key-value对,并返回value
void clear():清空当前map中的所有数据
元素查询的操作:
Object get(Object key):获取指定key对应的value
boolean containsKey(Object key):是否包含指定的key
boolean containsValue(Object value):是否包含指定的value
int size():返回map中key-value对的个数
boolean isEmpty():判断当前map是否为空
boolean equals(Object obj):判断当前map和参数对象obj是否相等
元视图操作的方法:
Set keySet():返回所有key构成的Set集合
Collection values():返回所有value构成的Collection集合
Set entrySet():返回所有key-value对构成的Set集合
总结:常用方法:
添加:put(Object key,Object value)
删除:remove(Object key)
修改:put(Object key,Object value)
查询:get(Object key)
长度:size()
遍历:keySet() values() entrySet()
* @author
* @create 2022-07-16 17:26
*/
public class MapTest {
/*
元视图操作的方法:遍历操作
Set keySet():返回所有key构成的Set集合
Collection values():返回所有value构成的Collection集合
Set entrySet():返回所有key-value对构成的Set集合
*/
@Test
public void test5(){
Map map = new LinkedHashMap();
map.put(123,"fyt");
map.put(12,"AA");
map.put("AA","AbA");
//遍历key集:keySet()
Set set = map.keySet();
Iterator iterator = set.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
System.out.println("*******************");
//遍历value集合:values()
Collection values = map.values();
for(Object obj:values){
System.out.println(obj);
}
//遍历所有的key-value: entrySet()
//方式一:
Set entrySet = map.entrySet();
Iterator iterator1 = entrySet.iterator();
while (iterator1.hasNext()){
Object o = iterator1.next();
//entrySet里面的元素都是entry
Map.Entry e = (Map.Entry)o;
System.out.println(e.getKey() + "---->" + e.getValue());
}
//方式二:
//通过key去找到value
}
/*
元素查询的操作:
Object get(Object key):获取指定key对应的value
boolean containsKey(Object key):是否包含指定的key
boolean containsValue(Object value):是否包含指定的value
int size():返回map中key-value对的个数
boolean isEmpty():判断当前map是否为空
boolean equals(Object obj):判断当前map和参数对象obj是否相等
*/
@Test
public void test4(){
Map map = new LinkedHashMap();
map.put(123,"AA");
map.put(12,"AA");
map.put("AA",123);
map.put("AA","AbA");
Object o = map.get(12);
System.out.println(o);
boolean containsKey = map.containsKey(12);
System.out.println(containsKey);
Object o1 = map.containsValue("AA");
System.out.println(o1);
}
/*
添加、删除、修改操作:
Object put(Object key,Object value):将指定key-value添加到(或修改)当前map对象中
void putAll(Map m):将m中的所有key-value对存放到当前map中
Object remove(Object key):移除指定key的key-value对,并返回value
void clear():清空当前map中的所有数据
*/
@Test
public void test2(){
Map map = new LinkedHashMap();
//添加
map.put(123,"AA");
map.put(12,"AA");
map.put("AA",123);
//修改
map.put("AA","AbA");
System.out.println(map);
Map map1 = new LinkedHashMap();
map1.put("CC",123);
map1.put("DD",123);
map.putAll(map1);
System.out.println(map);
//remove(Object obj)
Object value = map.remove("DD");
System.out.println(value);
System.out.println(map);
map.clear();
System.out.println(map);
}
@Test
public void test1(){
Map map = new LinkedHashMap();
map.put(123,"AA");
map.put(12,"AA");
map.put(13,"AA");
map.put(23,"AA");
System.out.println(map);
}
@Test
public void test(){
Map map = new HashMap();
// map = new Hashtable();
map.put(null,null);
}
}
package com.atguigu.java;
import org.junit.Test;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeMap;
/**
* @author
* @create 2022-07-17 14:30
*/
public class TreeMapTest {
//向TreeMap中添加key-value,要求key必须是由同一个类创建的对象。
//因为要按照key进行排序:自然排序,定制排序
@Test
public void test(){
TreeMap map = new TreeMap();
User u1 = new User("Tom",12);
User u2 = new User("Jerry",42);
User u3 = new User("Jack",45);
User u4 = new User("Rose",13);
map.put(u1,43);
map.put(u2,53);
map.put(u3,54);
map.put(u4,23);
Set set = map.entrySet();
Iterator iterator = set.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
//定制排序:
@Test
public void test1(){
TreeMap map = new TreeMap(new Comparator(){
@Override
public int compare(Object o1, Object o2) {
if (o1 instanceof User && o2 instanceof User){
User u1 = (User)o1;
User u2 = (User)o2;
return -Integer.compare(u1.getAge(),u2.getAge());
}
throw new RuntimeException("类型不一致");
}
});
User u1 = new User("Tom",12);
User u2 = new User("Jerry",42);
User u3 = new User("Jack",45);
User u4 = new User("Rose",13);
map.put(u1,43);
map.put(u2,53);
map.put(u3,54);
map.put(u4,23);
Set set = map.entrySet();
Iterator iterator = set.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
package com.atguigu.java;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
/**
* @author 李长勇
* @create 2022-07-17 17:05
*/
public class PropertiesTest {
//Properties:常用来处理配置文件。key和value都是String类型
public static void main(String[] args) throws IOException {
Properties pros = new Properties();
FileInputStream fis = new FileInputStream("jdbc.properties");
pros.load(fis);//加载流对应的文件
String name = pros.getProperty("name");
String password = pros.getProperty("password");
System.out.println(name);
System.out.println(password);
}
}
package com.atguigu.java;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Collections:操作Collection Map的工具类
*
* Collection 和 Collections的区别
*
* @author
* @create 2022-07-17 17:27
*/
public class CollectionsTest {
/*
排序操作:(均为static方法)
reverse(List):反转 List 中元素的顺序
shuffle(List):对 List 集合元素进行随机排序
sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换
查找、替换
Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回
给定集合中的最大元素
Object min(Collection)
Object min(Collection,Comparator)
int frequency(Collection,Object):返回指定集合中指定元素的出现次数
void copy(List dest,List src):将src中的内容复制到dest中
boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换
List 对象的所有旧值
*/
@Test
public void test1(){
List list = new ArrayList();
list.add(123);
list.add(45);
list.add(43);
list.add(-234);
list.add(4234);
// List dest = new ArrayList();
// Collections.copy(dest,list);//IndexOutOfBoundsException: Source does not fit in dest
//void copy(List dest,List src):将src中的内容复制到dest中:
List dest = Arrays.asList(new Object[list.size()]);
System.out.println(dest.size());
Collections.copy(dest,list);
System.out.println(dest);
/*
Collections 类中提供了多个 synchronizedXxx() 方法,该方法可使将指定集
合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全
问题.
*/
//返回的list1、map1就是线程安全的了
List list1 = Collections.synchronizedList(list);
Map map1 = Collections.synchronizedMap(map);
}
@Test
public void test(){
List list = new ArrayList();
list.add(123);
list.add(45);
list.add(43);
list.add(-234);
list.add(4234);
System.out.println(list);
// Collections.reverse(list);
// Collections.shuffle(list);
// Collections.sort(list);
// Collections.sort(list, new Comparator() {
// @Override
// public int compare(Object o1, Object o2) {
// return 0;
// }
// });
// Collections.swap(list,2,3);
int i = Collections.frequency(list, 123);
System.out.println(i);
}
}