Java第二十一天

Map

Map:键值对的集合|映射的集合
映射关系
Key --Value
key: 唯一的,无序的–>Set
value:无序的,可重复的 -->collection
注意:Map接口下所有的实现去重与无序都是根据键值对的key实现的
一个Key只能对应一个value

package student.Map05;import java.util.*;
public class Class001_Map {public static void main(String[] args) {Map<String, Integer> map=new HashMap<>();//V put(K key, V value)//将指定值与此映射中的指定键关联(可选操作)。   key相同value覆盖map.put("xiaosun",3000);map.put("xiaozhang",4000);map.put("xiaoliu",5000);map.put("xiaozhao",6000);Map<String, Integer> map2=new HashMap<>();map2.put("xiaowu",7000);map2.put("xiaowang",7000);map2.put("xiaozhou",8000);map2.put("xiaohao",9000);System.out.println(map);System.out.println(map.isEmpty());//void putAll(Map m)//将所有映射从指定映射复制到此映射(可选操作)。map.putAll(map2);System.out.println(map);//boolean containsKey(Object key)//如果此映射包含指定键的映射,则返回true 。System.out.println(map.containsKey("xiaoliu"));//boolean containsValue(Object value)//如果此映射将一个或多个键映射到指定值,则返回true 。System.out.println(map.containsValue(7000));//void clear()//从此映射中删除所有映射(可选操作)。map2.clear();System.out.println(map2);//static  Map of(K k1, V v1, K k2, V v2)//返回包含两个映射的不可修改映射。Map<String,Integer> map3 =Map.of("你若化成风",18,"我幻化成雨",20);//map3.put(" ",10);//java.lang.UnsupportedOperationException//V remove(Object key)//如果存在,则从此映射中删除键的映射(可选操作)。System.out.println("=======");System.out.println(map.remove("xiaowu"));System.out.println("map="+map);System.out.println("===========");//default V replace(K key, V value)//仅当当前映射到某个值时才替换指定键的条目。//default boolean replace(K key, V oldValue, V newValue)//仅当当前映射到指定值时才替换指定键的条目。System.out.println(map.replace("xiaozhou",8000,9));System.out.println(map);//V get(Object key)//返回指定键映射到的值,如果此映射不包含该键的映射,则返回null 。System.out.println(map.get("xiaoliu"));//int size()//返回此映射中键值映射的数量。System.out.println(map.size());System.out.println("=========================");//遍历方式//Collection values()   获取所有的value返回Collection<Integer> values=map.values();for (Integer in:values) {System.out.println(in);}System.out.println("============================");//Set keySet() 返回此映射中包含的键的Set视图。Set<String> keys=map.keySet();for (String str:keys) {System.out.println(str+"-->"+map.get(str));}System.out.println("===========================");//Set> entrySet() 返回此地图中包含的映射的Set视图。Set<Map.Entry<String,Integer>> entrys=map.entrySet();for (Map.Entry<String,Integer> entry:entrys){System.out.println(entry);}}
}

请添加图片描述
请添加图片描述

TreeMap

TreeMap:(TreeSet底层结构就是TreeMap维护的)
底层结构:红黑树
特点:可以根据键值对的key做升序排序
去重与排序:都是根据键值对的key实现,关注键值对key的比较器
去重:通过put做添加,key相同value覆盖
新增方法:新增了一些比较大小相关的方法
遍历方式:1)values 2)keySet 3)entrySet

package student.Map05;import java.util.TreeMap;
public class Class002_TreeMap {public static void main(String[] args) {//TreeMap() --> key的内部比较器//使用其键的自然顺序构造一个新的空树映射。TreeMap<Double,String> map=new TreeMap<>();map.put(1.0,"我");map.put(2.0,"欲");map.put(3.0,"迎");map.put(4.0,"风");System.out.println(map);//TreeMap(Comparator comparator)  -->key的外部比较器//构造一个新的空树映射,根据给定的比较器排序。TreeMap<Student,String> map1=new TreeMap<>((x,y)->y.getAge()-x.getAge());map1.put(new Student("小孙",22),"厦门大学");map1.put(new Student("小刘",23),"浙江大学");map1.put(new Student("小任",24),"南京理工大");map1.put(new Student("小王",21),"西安交大");System.out.println(map1);//Map.Entry ceilingEntry(K key)//返回与大于或等于给定键的最小键关联的键值映射,如果没有这样的键,则null 。//K ceilingKey(K key)//返回大于或等于给定键的最小键,如果没有这样的键,则null 。System.out.println(map1.ceilingEntry(new Student("小孙",22)));System.out.println(map1.ceilingKey(new Student("小王",21)));//Map.Entry floorEntry(K key)//返回与小于或等于给定键的最大键关联的键值映射,如果没有这样的键,则null 。//K floorKey(K key)//返回小于或等于给定键的最大键,如果没有这样的键,则null 。System.out.println(map1.floorEntry(new Student("小刘",23)));System.out.println(map1.floorKey(new Student("小任",24)));//Map.Entry firstEntry()//返回与此映射中的最小键关联的键值映射,如果映射为空,则null 。//K firstKey()//返回此映射中当前的第一个(最低)键。System.out.println(map1.firstEntry());System.out.println(map1.firstKey());//Map.Entry lastEntry()//返回与此映射中最大键关联的键值映射,如果映射为空,则null 。//K lastKey()//返回此映射中当前的最后一个(最高)键。System.out.println(map1.lastEntry());System.out.println(map1.lastKey());//Map.Entry higherEntry(K key)//返回与严格大于给定键的最小键关联的键值映射,如果没有这样的键,则null 。//K higherKey(K key)//返回严格大于给定键的最小键,如果没有这样的键,则返回null 。//Map.Entry lowerEntry(K key)//返回与严格小于给定键的最大键关联的键值映射,如果没有这样的键,则null 。//K lowerKey(K key)//返回严格小于给定键的最大键,如果没有这样的键,则返回null 。System.out.println(map1.higherEntry(new Student("小孙",23)));System.out.println(map1.lowerEntry(new Student("小孙",23)));System.out.println(map1.higherKey(new Student("小孙",23)));System.out.println(map1.lowerKey(new Student("小孙",23)));//Map.Entry pollFirstEntry()//删除并返回与此映射中最小键关联的键值映射,如果映射为空,则null 。//Map.Entry pollLastEntry()//删除并返回与此映射中最大键关联的键值映射,如果映射为空,则null 。System.out.println(map1.pollFirstEntry());System.out.println(map1.pollLastEntry());}
}
class Student implements Comparable<Student>{private String name;private int age;public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic int compareTo(Student o) {return o.name.compareTo(this.name);  //根据姓名做升序}
}

请添加图片描述

HashMap

HashMap:Map接口的基于哈希表的实现。此实现提供所有可选的映射操作,并允许null值和null键
底层结构:哈希表
jdk1.7及之前:数组+链表
jdk1.8及之后:数组+链表+红黑树
当单向链表中节点个数>8,要求节点数组长度>64,这时会将单向链表变为红黑树
初始容量(底层数组的容量):默认16->

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;|可以通过构造器指定

加载因子(计算扩容阈值)loadFactor:默认0.75->

static final float DEFAULT_LOAD_FACTOR = 0.75f; | 可以通过构造器指定

阈值(扩容临界值)threshold:

capacity*loadFactor

扩容机制(底层数组扩容机制):每次扩容原容量的2倍

newCap =oldCap<<1

注意:数组的长度为2的整数次幂
没有新增方法
此实现不同步

HashMap存储过程

1.对要存储的键值对的key调用hash方法,返回key的hash方法,返回key的hash值
int hash = (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
2.调用putVal方法,同时传递key的Hash值,key,value,在方法内部实现添加键值对数据
3.执行putVal方法
1)判断哈希表底层节点数组是否为null | 是否长度为0?如果是直接调用resize方法实现扩容

if( ( tab =table)==null || ( n=tab.length) ==0 )n =( tabl =resize()).length; 

2)更具key的hash值与数组长度计算位桶索引

int index =(n-1)&hash;

3)判断节点数组[index ] 是否存在数据,如果不存在,直接创建新节点放入节点数组[ index]位置,作为单向链表首节点

if ((p =tab[ i =(n-1) &hash])==null)
tab[ i ] =newNode(hash,key,value,null);

4)如果存在首节点,p
a):判断首节点p是否为key相同的节点,如是key相同的节点,记录它

if (p.hash==hash &&(k =p.key)==key|| (key ! =null && key.equals(k))))e=p;

b)判断首节点p是否为红黑树中的节点,如果是,调用putTreeVal方法实现添加,如果不是继续向下判断
c)顺着单向链表首节点p遍历整个链表,直到找到key相同的节点e,或者遍历到原链表的最后创建新节点挂上去,结束

找到key相同的节点:if( e.hash ==hash &&( (k =e.key)==key||(key!=null && key.equals(k))))break;遍历到原链表的后创建新节点挂上去:if ( (e =p.next)==null)p.next =newNode(hash,key,value,null);

5)判断是否存在key相同的节点,如果存在,覆盖,返回原value的值,方法结束

if( e! =null){V oldValue =e.value;e.value =value;return oldValue;
}

6)如果不存在key相同的节点,肯定在之前创建新节点放入到了哈希表中,长度+1,判断是否需要扩容,

if(++size>threshold)resize();

7)最后返回null

return null;

步骤较为重要,代码重在理解,理解源代码才能更好地理解运行过程

Hashtable

Hashtable 与HashMap之间的区别
共同点
都Map接口的实现类,都存储键值对数据
底层结构都是哈希表,特点相同
不同点
1.继承体系
HashMap继承自java.util.AbstractMap< K ,V>
Hashtable继承自java.util.Dictionary
2.对null处理不同
HashMap:允许null值和null键
Hashtable:任何非null对象都可以用作键或值
3.同步问题
HashMap 线程不安全|不同步的
Hashtable 线程安全|同步的
如果不需要线程安全实现,建议使用HashMap代替Hashtable。如果需要线程安全的高并发实现,则建议使用ConcurrentHashMap代替Hashtable
4.计算hash值与位桶索引的方式不同
HashMap:
int hash = (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
int index = (n - 1) & hash;
Hashtable:
int hash= key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
5.初始容量与扩容机制不同
HashMap:
初始容量:16|可以通过构造器指定
扩容机制:每次扩容原容量的2倍 newCap =oldCap<<1
Hashtable:
初始容量:11|可以通过构造器指定
==扩容机制:每次扩容原容量的2倍+1 ==
int newCapacity = (oldCapacity << 1) + 1;
如何处理HashMap线程不安全问题
1.Hashtable
2.Collections–>static MapsynchronizedMap(Map,m) 返回由指定映射支持的同步(线程安全)映射
3.juc–>ConcurrentHashMap = =>推荐

package student.Map05;import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class Class004_Hashtable {public static void main(String[] args) {ConcurrentHashMap<String,Integer> map =new ConcurrentHashMap<>();map.put("慈悲",1);map.put("留几分",2);Map<String,Integer> m = Collections.synchronizedMap(map);System.out.println(m);}
}

请添加图片描述

Properties

Properties:
Properties类表示一组持久的属性
Properties可以保存到流中或从流中加载
属性列表中的每个键及其对应的值都是一个字符串
一般使用Properties的作用都是从配置文件中加载键值对数据

package student;import java.io.*;
import java.util.Properties;
public class Class001_Properties {public static void main(String[] args) throws IOException {Properties p =new Properties();p.setProperty("xiaosun","lihai");p.setProperty("xiaosunsun","chaolihai");p.setProperty("chaojiwudixiaosunsun","chaojilihai");//void store(OutputStream out, String comments)//将此Properties表中的属性列表(键和元素对)以适合使用load(InputStream)方法加载到Properties表的格式写入输出流。OutputStream os =new BufferedOutputStream(new FileOutputStream("src/test.properties")) ;p.store(os,"aaaa");os.flush();os.close();System.out.println(p.getProperty("xiaosun"));//从流中加载 | 从配置文件中加载键值对数据//void load(InputStream inStream)//从输入字节流中读取属性列表(键和元素对)。p.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));System.out.println(p);System.out.println(p.getProperty("name"));}
}

请添加图片描述
请添加图片描述


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部