码迷,mamicode.com
首页 > 其他好文 > 详细

Map学习

时间:2020-02-22 16:07:24      阅读:69      评论:0      收藏:0      [点我收藏+]

标签:get   variant   str   tostring   遍历   规则   move   res   stat   

键不可以重复,值可以重复,每个键只能对应一个值

1.HashMap——底层是数组+链表,线程不安全(允许存放null键<只能一个null值键>和null值,当键为null时把对应值放在数组首位 )(HashMap有一个子类LinkedHashMap,可以根据存入顺序进行
技术图片

 

 

HashMap采用Entry数组来存储key-value对,每一个键值对组成了一个Entry实体,Entry类实际上是一个单向的链表结构,它具有Next指针,可以连接下一个Entry实体,依次来解决Hash冲突的问题,因为HashMap是按照Key的hash值来计算Entry在HashMap中存储的位置的,如果hash值相同,而key内容不相等,那么就用链表来解决这种hash冲突。(用数组存储,当hash值冲突时就用链表依次连接<采用链表解决hash冲突>)
技术图片

 

 

技术图片
 
HashMap的存储
1. public V put(K key, V value) {  
2.     // HashMap允许存放null键和null值。  
3.     // 当key为null时,调用putForNullKey方法,将value放置在数组第一个位置。  
4.     if (key == null)  
5.         return putForNullKey(value);  
6.     // 根据key的keyCode重新计算hash值。  
7.     int hash = hash(key.hashCode());  
8.     // 搜索指定hash值在对应table中的索引。  
9.     int i = indexFor(hash, table.length);  
10.     // 如果 i 索引处的 Entry 不为 null,通过循环不断遍历 e 元素的下一个元素。  
11.     for (Entry<K,V> e = table[i]; e != null; e = e.next) {  
12.         Object k;  
13.         if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {  
14.             V oldValue = e.value;  
15.             e.value = value;  
16.             e.recordAccess(this);  
17.             return oldValue;  
18.         }  
19.     }  
20.     // 如果i索引处的Entry为null,表明此处还没有Entry。  
21.     modCount++;  
22.     // 将key、value添加到i索引处。  
23.     addEntry(hash, key, value, i);  
24.     return null;  
25. }  
技术图片

 

技术图片

 

 

  1. 先计算新加入键值对的hash值(第七行
  2. 在根据hash值和数组长度取余,得到在数组中的一个索引(第九行)
  3. 如果这个位置有Entry,先查找这个Entry链表中有没有和给的键值对key相同的,如果有的话用新的value覆盖旧的value
  4. 最后将这个新的键值对放在这个链表的链头,链尾是最先加入的元素,如果数组该位置上没有元素就直接把这个元素放进去
(查找的时候也是同理,先通过计算key的hash值找到table的对应位置,然后在这个位置中挨个遍历找到与之相同的key)
 
  • put(K key, V value)——存值
  • putAll(Map map)——添加一个同类型Map
  • get(Object key)——根据键名取值
  • isEmpty()——判断是否为空
  • containsKey(Object key)——判断是否含有key
  • containsValue(Object value)——判断是否含有value
  • remove(Object key)——删除这个key值下的value
  • size()——Hashmap的元素个数
  • values()——返回存放value值的Collection集合
  • keySet()——返回存放key值的Set集合
  • entrySet()——返回包含映射关系的Set集合(就是把Key-Value作为一个一个整体存放到Set集合中去)------- 通过getKey()和getValue()方法获得键和值
—————————————————————————————————————————————————

四种遍历map的方式

Entry
由于Map中存放的元素均为键值对,故每一个键值对必然存在一个映射关系。
Map中采用Entry内部类来表示一个映射项,映射项包含Key和Value (我们总说键值对键值对, 每一个键值对也就是一个Entry)
Map.Entry里面包含getKey()和getValue()方法
Iterator<Map.Entry<Integer, Integer>> it=map.entrySet().iterator();
while(it.hasNext()) {
Map.Entry<Integer,Integer> entry=it.next();
int key=entry.getKey();
int value=entry.getValue();
System.out.println(key+" "+value);
}
entrySet
entrySet是 java中 键-值 对的集合,Set里面的类型是Map.Entry,一般可以通过map.entrySet()得到。
entrySet实现了Set接口,里面存放的是键值对。一个K对应一个V。
用来遍历map的一种方法。
Set<Map.Entry<String, String>> entryseSet=map.entrySet();
for (Map.Entry<String, String> entry:entryseSet) {
System.out.println(entry.getKey()+","+entry.getValue());
}
即通过getKey()得到K,getValue得到V。
keySet
还有一种是keySet, keySet是键的集合,Set里面的类型即key的类型
Set<String> set = map.keySet();
for (String s:set) {
System.out.println(s+","+map.get(s));
}
—————————————————————————————————————————————————
(enteySet速度要比keySet速度快得多)
  • replace(key, value)——把key值对应的值改成value
  • clear()——清空Map
 
 
2.Hashtable——底层是数组+链表,线程安全(不允许key和value为null )
 
3.TreeMap——底层是红黑树,线程不安全(不允许key为null,允许value为null)
(Map的方法他都有)
  • public Map.Entry<K,V> ceilingEntry(K key)——返回指定的Key大于或等于的最小值的元素(返回的是Entry),如果没有,则返回null
  • public K ceilingKey(K key)—— 返回指定的Key大于或等于的最小值的Key(返回的是key的值),如果没有,则返回null
  • public Map.Entry<K,V> firstEntry()——返回集合最小key的元素(返回的是Entry)
  • public Map.Entry<K,V> lastEntry()——返回集合最大Key的元素(返回的是Entry)
  • public K firstKey()——返回集合中最小Key的key
  • public K lastKey()——返回集合中最大Key的key
 
3.1 TreeMap排序
技术图片

 

 

技术图片
实现排序的有两个接口Comparable和Comparator接口
  1. Comparable:内部比较器,需要在类的内部重写compareTo方法
  2. Comparator:外部比较器,无需改变类的结构,用于那些没有实现Comparable接口或者已经实现Comparable接口但是对排序规则不满意的,需要重新写一个比较器类,实现Comparator接口,重写compare方法
  • 用this对象-参数对象,就是升序
  • 用参数对象-this对象,就是降序
 
例子:
1.comparable
public class SortedTest implements Comparable<SortedTest> {
private int age;
public SortedTest(int age){
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//自定义对象,实现compareTo(T o)方法:
public int compareTo(SortedTest sortedTest) {
int num = this.age - sortedTest.getAge();
//为0时候,两者相同:
if(num==0){
return 0;
//大于0时,传入的参数小:
}else if(num>0){
return 1;
//小于0时,传入的参数大:
}else{
return -1;
}
}}
 
public class TreeMapTest {
public static void main(String[] agrs){
//自然顺序比较
naturalSort();
}
//自然排序顺序:
public static void naturalSort(){
//第一种情况:Integer对象
TreeMap<Integer,String> treeMapFirst = new TreeMap<Integer, String>();
treeMapFirst.put(1,"jiaboyan");
treeMapFirst.put(6,"jiaboyan");
treeMapFirst.put(3,"jiaboyan");
treeMapFirst.put(10,"jiaboyan");
treeMapFirst.put(7,"jiaboyan");
treeMapFirst.put(13,"jiaboyan");
System.out.println(treeMapFirst.toString());
 
//第二种情况:SortedTest对象
TreeMap<SortedTest,String> treeMapSecond = new TreeMap<SortedTest, String>();
treeMapSecond.put(new SortedTest(10),"jiaboyan");
treeMapSecond.put(new SortedTest(1),"jiaboyan");
treeMapSecond.put(new SortedTest(13),"jiaboyan");
treeMapSecond.put(new SortedTest(4),"jiaboyan");
treeMapSecond.put(new SortedTest(0),"jiaboyan");
treeMapSecond.put(new SortedTest(9),"jiaboyan");
System.out.println(treeMapSecond.toString());
}}
2.comparator
public class SortedTest {
private int age;
public SortedTest(int age){
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}}
public class SortedTestComparator implements Comparator<SortedTest> {
//自定义比较器:实现compare(T o1,T o2)方法:
public int compare(SortedTest sortedTest1, SortedTest sortedTest2) {
int num = sortedTest1.getAge() - sortedTest2.getAge();
if(num==0){//为0时候,两者相同:
return 0;
}else if(num>0){//大于0时,后面的参数小:
return 1;
}else{//小于0时,前面的参数小:
return -1;
}
}}
 
public class TreeMapTest {
public static void main(String[] agrs){
//自定义顺序比较
customSort();
}
//自定义排序顺序:
public static void customSort(){
TreeMap<SortedTest,String> treeMap = new TreeMap<SortedTest, String>(new SortedTestComparator());
treeMap.put(new SortedTest(10),"hello");
treeMap.put(new SortedTest(21),"my");
treeMap.put(new SortedTest(15),"name");
treeMap.put(new SortedTest(2),"is");
treeMap.put(new SortedTest(1),"jiaboyan");
treeMap.put(new SortedTest(7),"world");
System.out.println(treeMap.toString());
}}
—————对象在比较的时候要重写equals()和hashCode()方法,这样才能比较对象的是否相等————————————————
技术图片

 

 

 

 

Map学习

标签:get   variant   str   tostring   遍历   规则   move   res   stat   

原文地址:https://www.cnblogs.com/beeenwei/p/12345516.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!