HashMap常见键、LinkedHashMap以及TreeMap的理解

HashMap四种常见的键的类型:

HashMap<String,String>HashMap<Integer,String>HashMap<String,Student>HashMap<Student,String>(其中的Student只是我们自定义的一个学生类)

例如:

package com.westos.HashMap;
 
import java.util.HashMap;
import java.util.Set;
 
/**
 *HashMap(String (学号),String(姓名))形式
 */
public class HashMapDome {
 
public static void main(String[] args) {
//创建HashMap集合的对象
HashMap<String,String> map=new HashMap<String,String>();
map.put("132614", "曹乾");
map.put("132118", "刘崇华");
map.put("132194", "马玉超");
map.put("132668", "宋晓波");
map.put("132668", "于金乐");
map.put("132614", "井杰");
//收集集合中所有的键对象
Set<String> key = map.keySet();
//增强for循环
for(String str:key) {
//获取所有与键对应的值
String value = map.get(str);
System.out.println(str+"----"+value);
}
}
}
 
运行结果:
132614----井杰
132118----刘崇华
132668----于金乐
132194----马玉超

例如:

package com.westos.HashMap;
 
import java.util.HashMap;
import java.util.Set;
 
/**
 *HashMap<Integer(年龄),String(姓名)>形式
 *
 */
public class HashMapDome2 {
 
public static void main(String[] args) {
//创建HashMap集合的对象
HashMap<Integer,String> map=new HashMap<Integer,String>();
//添加集合中的元素
map.put(25, "Angelababy");
map.put(23, "吴宣仪");
map.put(24, "赵星星");
map.put(22, "孟美岐");
map.put(25, "迪丽热巴");
//获取集合中所有的键
Set<Integer> keySet = map.keySet();
//增强for循环
for(Integer key:keySet) {
String value = map.get(key);
//遍历出每一个键和它对应的值
System.out.println(key+"----"+value);
}
}
}
运行结果:
22----孟美岐
23----吴宣仪
24----赵星星
25----迪丽热巴

package com.westos.HashMap;
 
public class Student {
 
private String name;
private int age;
public Student() {
super();
}
public Student(String name, int age) {
super();
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;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}


}

 

package com.westos.HashMap;
/**
 * HhashMap<String(学号),Student(学生的姓名和年龄)
 */
import java.util.HashMap;
import java.util.Set;
 
public class HashMapDome3 {
 
public static void main(String[] args) {
//创建HashMap集合对象
HashMap<String,Student> map=new HashMap<String,Student>();
//创建学生对象
Student s1=new Student("迪丽热巴",25);
Student s2=new Student("吴宣仪",23);
Student s3=new Student("孟美岐",23);
Student s4=new Student("赵星星",24);
Student s5=new Student("迪丽热巴",25);
//将学生对象添加进集合中去
map.put("001", s1);
map.put("002", s2);
map.put("003", s3);
map.put("004", s4);
map.put("005", s5);
//获取集合中所有的键
Set<String> set = map.keySet();
//增强for循环
for(String key:set) {
Student value = map.get(key);
System.out.println(key+":"+value.getName()+"----"+value.getAge()); 
}
}
}
运行结果:
001:迪丽热巴----25
002:吴宣仪----23
003:孟美岐----23
004:赵星星----24
005:迪丽热巴----25

例如:

学生类就用了上面的那个学生类

package com.westos.HashMap;
/**
 * HashMap<Student,String>类型
 */
import java.util.HashMap;
import java.util.Set;
 
public class HashMapDome4 {
 
public static void main(String[] args) {
//创建HashMap集合对象
HashMap<Student,String> map=new HashMap<Student,String>();
//创建学生对象
Student s1=new Student("迪丽热巴",25);
Student s2=new Student("吴宣仪",23);
Student s3=new Student("孟美岐",23);
Student s4=new Student("赵星星",24);
Student s5=new Student("迪丽热巴",25);
//将学生对象添加进集合中去
map.put( s1,"001");
map.put( s2,"002");
map.put( s3,"003");
map.put( s4,"004");
map.put( s5,"005");
//获取集合中所有的键
Set<Student> set = map.keySet();
//for循环
for(Student key:set) {
String value = map.get(key);
System.out.println(key.getName()+"="+key.getAge()+"--"+value);
}
}
}
运行结果:
赵星星=24--004
吴宣仪=23--002
迪丽热巴=25--005
孟美岐=23--003

从最后的这个HashMap<Student,String>类型中当我们的键(就是学生类的对象)内容一样时,运行结果中后面的那个一样的键的值替代了前面的那个键的值,要想达到这种去重的效果,必须在自定义类中添加重写方法(equals方法和HashCode方法),因为我们是自定义类,调用自定义对象时,在底层代码中系统并没有帮我们重写这两个方法,所以必须我们自己手动重写,否则达不到去重的效果

LinkedHashMap集合

我们都知道HashMap的无序性(存储和输出的顺序不一致),但是当我们需要HashMap的唯一性,还想要它能有序的输出,应该怎么做呢?

LinkHashMap可以帮我们解决这个问题:

它是基于哈希表和链接列表实现的

其中HashMap可以解决唯一性的问题,Linked可以解决有序性的问题

例如:

package com.westos.HashMap;
 
import java.util.LinkedHashMap;
import java.util.Set;
 
public class LinkedHashMapDome {
 
public static void main(String[] args) {
//创建集合对象
LinkedHashMap<String,String> link=new LinkedHashMap<String,String>();
//向集合中添加元素
link.put("迪丽热巴", "美女");
link.put("吴宣仪", "少女");
link.put("孟美岐", "大哥");
link.put("古天乐", "型男");
link.put("萧炎", "斗帝");
//获取集合中所有的键
Set<String> set = link.keySet();
//for循环
for(String key:set) {
//获取键对应的值
String value = link.get(key);
System.out.println(key+"----"+value);
}
}
}
运行结果:
迪丽热巴----美女
吴宣仪----少女
孟美岐----大哥
古天乐----型男
萧炎----斗帝

TreeMap集合

前面我们学习了treeSet集合,其中了解两种遍历方式:自然排序和比较器排序,接下来让我们看看TreeMap集合

先简单的说说TreeSetTreeMap的区别?

TreeMapMap接口常用的子实现类,而TreeSetSet接口常用的子实现类,TreeSet底层是通过TreeMap来实现的,(就相当于HashSet底层是通过HashMap来实现的),TreeMap是依靠红黑树结构来实现的

相同点:他们都是有序的集合

不同点:他们实现于不同的接口

存储的类型数量不同(treeSet只能存储一种类型,TreeMap可以存储存储两种类型(keyvalue))

那让我们看看TreeMap存储自定义对象的例子

例如:

先创建一个自定义类

package com.westos.TreeMap;
 
public class Student {
 
private String name;
private int age;

public Student() {
super();
}

public Student(String name, int age) {
super();
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;
}

}

再创建一个测试类:

package com.westos.TreeMap;
 
import java.util.Comparator;
import java.util.Set;
import java.util.TreeMap;
 
public class TreeMapDome {
 
public static void main(String[] args) {
//创建TreeMap集合对象,并且运用比较器排序的方式
TreeMap<Student,String> map=new TreeMap<Student,String>(new Comparator<Student>() {
 
@Override
public int compare(Student s1, Student s2) {
// return 0;
//按年龄(从小到大)来排序
int num=s1.getAge()-s2.getAge();
//当年龄大小一样时,比较姓名
int num2=num==0?s1.getName().compareTo(s2.getName()):num;
return num2;
}

});
//创建学生类对象
Student s1=new Student("旺达",29);
Student s2=new Student("幻视",32);
Student s3=new Student("黑寡妇",32);
Student s4=new Student("雷神",35);
Student s5=new Student("托尼",37);
Student s6=new Student("托尼",37);
//将学生对象添加到集合中
map.put(s1, "菜鸟");
map.put(s2, "美女");
map.put(s3, "御姐");
map.put(s4, "锤子");
map.put(s5, "钢铁侠");
map.put(s6, "小辣椒");
//获取集合中所有的键
Set<Student> set = map.keySet();
for(Student key:set) {
//获取键所对应的所有的值
String value = map.get(key);
System.out.println(key.getName()+","+key.getAge()+":"+value);
}
}
}
运行结果:
旺达,29:菜鸟
幻视,32:美女
黑寡妇,32:御姐
雷神,35:锤子
托尼,37:小辣椒

前面我们学习了ArrayList集合的嵌套遍历,接下来让我们看看HashMap集合的嵌套

例如:

package com.westos.HashMap2;
 
import java.util.HashMap;
import java.util.Set;
 
/**
 * 一个大集合LPL(中国LOL战队)HashMap<HashMap<Person>>
 * 三个小集合HashMap<Person> RNG战队,EDG战队,IG战队
 *
 */
public class HashMapTest {
 
public static void main(String[] args) {
//创建大集合
HashMap<String,HashMap<String,String>> lol=new HashMap<String,HashMap<String,String>>();
//创建第一个小集合
HashMap<String,String> rng=new HashMap<String,String>();
//向集合中添加元素
rng.put("Uzi", "ADC");
rng.put("Mlxg", "打野");
//将小集合添加到大集合中
lol.put("RNG", rng);
//创建第二个小集合
HashMap<String,String> edg=new HashMap<String,String>();
//向集合中添加元素
edg.put("那美", "ADC");
edg.put("厂长", "打野");
//添加到大集合中
lol.put("EDG",edg);
//创建第三个小集合
HashMap<String,String> ig=new HashMap<String,String>();
//添加元素
ig.put("Acorn","ADC");
ig.put("Clearlove","打野");
//添加到大集合中
lol.put("IG", ig);
//获取大集合中的所有键
Set<String> set = lol.keySet();
//for循环遍历
for(String hash:set) {
System.out.println(hash+":");
//获取大集合中的所有值,返回的是小集合的类型
HashMap<String, String> value = lol.get(hash);
//然后再获取小集合的所有键,就相当于我们创建一个HashMap集合给他遍历,不要管上面的那些大集合
Set<String> Hashset = value.keySet();
//循环遍历小集合
for(String key:Hashset) {
//获取小集合中的所有值
String str = value.get(key);

System.out.println("\t"+key+":"+str);
}

}
}
}
运行结果:
EDG:
厂长:打野
那美:ADC
RNG:
Uzi:ADC
Mlxg:打野
IG:
Clearlove:打野
Acorn:ADC
 

让我们再看看HashtableHashMap的区别?

面试题:

  HashMap集合和Hashtable的区别?

  共同点:都是map接口的实现类,都是基于哈希表的实现类

HashMap集合线程不安全的类,不同步,执行效率高(允许键和值是null)

Hashtable集合线程安全的类,同步,执行效率低(不允许有null键和null)

 

package com.westos.HashMap2;
 
import java.util.HashMap;
import java.util.Hashtable;
 
public class HashTable {
public static void main(String[] args) {
//创建HashMap集合对象
HashMap<String,String> hm=new HashMap<String,String>();
//创建Hashtable集合对象
Hashtable<String,String> ht=new Hashtable<String,String>();
hm.put(null, "java");
//ht.put(null, "baby");//Exception in thread "main" java.lang.NullPointerException
System.out.println("hm:"+hm);
System.out.println("ht:"+ht);
}
 

}
运行结果:
hm:{null=java}
ht:{}

由上例看出

Hashtable集合不论是键还是值都不允许有null值,否则编译通过,运行就会报错,而HashMap中的则允许有null值,编译和运行都会通过

我们目前学习过的线程安全的类有:StringBuffer(字符串缓冲区)、vectorlist集合子实现类)、HashtableMap集合子实现类)

让我们用HashMap集合来看一个集合

需求:

字符串:比如: aaaaabbbbcccddddee   ,最终控制台要出现的结果:a(5)b(4)c(3)d(3)e(2)

 

package com.westos.TreeMap;
 
import java.util.HashMap;
import java.util.Scanner;
import java.util.Set;
 
/**
 *需求:
 * 字符串:比如: aaaaabbbbcccddddee   ,最终控制台要出现的结果:a(5)b(4)c(3)d(3)e(2)
 * 
 *思路:
 * 1)改进:键盘录入一个字符串
 * 2)创建一个HashMap集合key:Character,Value:Integer
 * 3)将录入的字符串转换成字符数组
 * 4)遍历可以获取每一个字符
 *
 * 5)将元素添加到对应的HashMap集合中
 * 使用的put(key,value): 通过判断值是否null ,如果是null表示第一次存储
 * 集合对象.put(ch,1) ;
 * 否则,不是null
 * Integer那个值++;
 * 集合对象.put(ch,变量Integer值)  ;
 *
 * 6)遍历HashMap集合即可
 *
 */
public class HashMapDome {
 

public static void main(String[] args) {
//键盘录入
Scanner sc=new Scanner(System.in);
System.out.println("输入一个字符串...");
String str=sc.nextLine();
//将字符春转换成字符数组
char[] array = str.toCharArray();
//创建集合对象
HashMap<Character,Integer> map=new HashMap<Character,Integer>();
//遍历字符数组
for(Character ch:array) {
//获取数组中的每一个字符
Integer value = map.get(ch);
//判断数组是否为null,如果是给集合中添加元素
if(value==null) {
map.put(ch, 1);
}else {
value++;
map.put(ch,value);
}
}
//创建一个字符串缓冲区
StringBuffer sb=new StringBuffer();
//获取集合的键
Set<Character> set = map.keySet();
//遍历HashMap集合的值
for(Character key:set) {
//获取集合中的值
Integer num = map.get(key);
sb.append(key).append("(").append(num).append(")");
}
//将缓冲区中的字符转换成字符串
String str2 = sb.toString();
System.out.println(str2);

 
}
}
运行结果:
输入一个字符串...
helloworld
r(1)d(1)e(1)w(1)h(1)l(3)o(2)

猜你喜欢

转载自blog.csdn.net/j_better/article/details/80370670
今日推荐