Map集合
需求:有很多学生,学生有姓名,有学号,根据学生的学号查找学生?
之前学习的集合,可以将姓名,学号作为学生类的中两个成员变量,创建集合的时候存储这个类型,可以的
Key Value
学号1 姓名1
学号2 姓名2
学号3 姓名3
学号1(重复的键) 姓名4
Java针对这种技术----->Map集合 ,反映键值映射关系的一种集合(接口)
将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。
Map<K,V> ,在Map集合中,只对键有效,跟值无关 Map接口的子实现类:HashMap和TreeMap
面试题:
Map集合和Collection的区别?
Map集合:是键和值的映射关系(双列集合) 当作为:夫妻对
Collection集合:单列集合,只能存储一种类型的元素,当作为:光棍
间接关系:HashSet依赖于Map接口的子实现类HashMap
TreeSet依赖于Map接口的子实现类TreeMap
Map接口的功能:
V put(K key,V value) :添加功能:将指定的值和键关联起来
如果当前的这个键是第一次存储,则返回null
如果当前的键不是第一次存储,则返回上一次所存储的value,当前的值就把之前的键所对应的值替换掉!
获取功能
Set<Map.Entry<K,V>> entrySet() :和Map集合的遍历有关系(键值对对象)
Set<K> keySet():获取映射关系中所有键的集合
int size()返回此映射中键-值映射关系数
删除功能
void clear():删除所有映射关系
Vremove(Object key)如果存在一个键的映射关系,则将其从此映射中移除
判断功能:
boolean containsKey(Object key)如果此映射包含指定键的映射关系,则返回 true
boolean containsValue(Object value):映射关系中是否包含指定的值
boolean isEmpty():判断映射关系是否为空
代码示例
package test;
import java.util.HashMap;
import java.util.Map;
public class TestDemo {
public static void main(String[] args) {
// 创建Map集合对象
Map<String, String> map = new HashMap<String, String>();
// System.out.println("map:"+map);
// 添加功能的作用
// System.out.println("put1():"+map.put("文章", "马伊琍"));
// System.out.println("map:"+map);
// System.out.println("put2():"+map.put("文章", "姚笛"));
// System.out.println("map:"+map);
// System.out.println("put3():"+map.put("文章", "高圆圆"));
// System.out.println("map:"+map);
// System.out.println("put4():"+map.put("文章", "马蓉"));
// 添加元素
map.put("赵又廷", "高圆圆");
map.put("周杰伦", "昆凌");
map.put("黄晓明", "babay");
map.put("文章", "马伊琍");
// void clear():删除所有映射关系
// map.clear();
// V remove(Object key)如果存在一个键的映射关系,则将其从此映射中移除,返回的是该键所对应的值
// System.out.println("remove():"+map.remove("黄晓明"));
// boolean containsKey(Object key)如果此映射中包含指定键所对应的映射关系,则返回 true
System.out.println("containsKey():" + map.containsKey("杨过"));
System.out.println("containsKey():" + map.containsKey("赵又廷"));
// boolean containsValue(Object value):映射关系中是否包含指定的值
System.out.println("containsValue():" + map.containsValue("昆凌"));
System.out.println("map:" + map); // {key1=value1, key2=value2,.}
}
}
这种遍历方式实际开发中经常用到
Set<K> keySet():获取映射关系中所有键的集合
V get(Object key):通过键找值
转换法:
1)将所有的丈夫集中起来
2)让丈夫对应其妻子
3)将他们遍历出来
思路:
1)获取映射关系中所有键的集合
2)通过键找它对应的值
3)遍历即可
代码示例
package test;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class TestDemo2 {
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("杨过", "小龙女");
map.put("郭靖", "黄蓉");
map.put("文章", "马伊琍");
map.put("赵又延", "高圆圆");
// System.out.println("map"+map);
Set<String> set = map.keySet();// 获取所有键的集合set
for (String a : set) {// 遍历所有的键,获取所对应的值(value)
String value = map.get(a);
System.out.println(a + "=" + value);
}
}
}
Map集合的另一种遍历的方式Set<Map.Entry<K,V>> entrySet() (键值对对象)
转换法: 1)获取所有的结婚证 2)通过每一个结婚证去找对应的丈夫和妻子 3)遍历输出
思路:1)获取所有的键值对对象entrySet() Set<Map.Entry<String, String>> entrySet entrySey只在增强for中使用
2)获取每一个键值对对象Map.Entry<String, String> entry 通过entry.getKey(),entry.getValue()获取对应的键和值
3)遍历
代码示例
package test;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class TestDemo3 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Map<String, String> map = new HashMap<String, String>();
map.put("杨过", "小龙女");
map.put("郭靖", "黄蓉");
map.put("黄晓明", "baby");
map.put("赵又延", "高圆圆");
// 获取所有的键值对对象
Set<Map.Entry<String, String>> entrySet = map.entrySet();
for (Map.Entry<String, String> entry : entrySet) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key + "=" + value);
}
}
}
需求:
使用HashMap集合存储自定义对象,键分别为引用类型和自定义类型
1)键为引用类型String,值为自定义类型Student
代码示例
定义自定义类型Student
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 hashmap;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;;
public class HashMapDemo2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
HashMap<String, Student> map = new HashMap<String, Student>();
// Key为系统预定义类型String
Student s1 = new Student("西施", 27);
Student s2 = new Student("杨贵妃", 35);
Student s3 = new Student("王昭君", 30);
Student s4 = new Student("貂蝉", 28);
Student s5 = new Student("西施", 27);
map.put("001", s1);
map.put("000", s4);
map.put("005", s5);
map.put("002", s2);
map.put("003", s3);
map.put("001", s1);
map.put("000", s4);
map.put("005", s5);
map.put("002", s2);
map.put("003", s3);
Set<Entry<String, Student>> entrySet = map.entrySet();
for (Entry<String, Student> entry : entrySet) {// entrySet为所有键值对对象
// entry为一个键值对对象
String key = entry.getKey();
Student value = entry.getValue();
System.out.println(key + "----" + value);
}
}
}
2 )键为自定义类型Student,值为引用类型String
代码示例
由于自定义类型Student没有重写哈希表的hashCode()和equals()方法,所以在Student类中重写这两个方法
package 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 hashmap;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class HashMapDemo3 {
public static void main(String[] args) {
// TODO Auto-generated method stub
HashMap<Student, String> map = new HashMap<Student, String>();
Student s1 = new Student("西施", 27);
Student s2 = new Student("杨贵妃", 35);
Student s3 = new Student("王昭君", 30);
Student s4 = new Student("貂蝉", 43);
Student s5 = new Student("西施", 2);
map.put(s1, "元朝");
map.put(s2, "宋朝");
map.put(s3, "唐朝");
map.put(s4, "清朝");
map.put(s5, "金朝");
Set<Map.Entry<Student, String>> entry = map.entrySet();
for (Map.Entry<Student, String> entry2 : entry) {
Student key = entry2.getKey();
String value = entry2.getValue();
System.out.println(key.getName() + "-----" + key.getAge() + "----" + value);
}
}
}
LinkedHashMap<K,V> :是Map接口基于哈希表和链接列表实现的
哈希表保证键的唯一性
链接列表保证元素的有序性(存储和取出一致)
代码示例
package hashmap;
import java.util.LinkedHashMap;
import java.util.Set;
public class linkedHashMapDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
map.put("0001", "hello");
map.put("004", "java");
map.put("009", "world");
map.put("020", "javaee");
Set<String> set = map.keySet();// 获取键所在的集合
for (String key : set) {
String value = map.get(key);
System.out.println(key + "----" + value);
}
}
}
TreeMap
package 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 TreeMap;
import java.util.Set;
import java.util.TreeMap;
public class TreeMapDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
TreeMap<String, String> tm=new TreeMap<String,String>();
tm.put("hello", "哈喽") ;
tm.put("world", "世界") ;
tm.put("java", "爪哇") ;
tm.put("hello", "哈喽2") ;
tm.put("world", "世界2") ;
tm.put("java", "爪哇2") ;
tm.put("hello", "哈喽3") ;
tm.put("world", "世界3") ;
tm.put("java", "爪哇3") ;
Set<String> set=tm.keySet();
for (String key : set) {
String value=tm.get(key);
System.out.println(key+"------"+value);
}
}
}
当TreeMap中键为自定义类型(Student)并且需要按照年龄从小到大排序,则使用比较器排序,(Comparator接口的匿名内部类,在匿名内部类中重写compare()方法
代码示例
package TreeMap;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeMap;
public class TreeMapDemo2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
TreeMap<Student, String> tm = new TreeMap<Student, String>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
// TODO Auto-generated method stub
// return 0;
int num = o1.getAge() - o2.getAge();
int num2 = num == 0 ? o1.getName().compareTo(o2.getName()) : num;
return num2;
}
});
Student s1 = new Student("唐伯虎", 28);
Student s2 = new Student("杜甫", 35);
Student s3 = new Student("李白", 40);
Student s4 = new Student("李清照", 32);
Student s5 = new Student("唐伯虎", 28);
Student s6 = new Student("苏轼", 35);
Student s7 = new Student("唐伯虎", 29);
tm.put(s1, "宋代");
tm.put(s2, "唐代");
tm.put(s3, "唐代");
tm.put(s4, "宋代");
tm.put(s5, "清代");
tm.put(s6, "清代");
tm.put(s7, "民国");
Set<Student> set = tm.keySet();
for (Student key : set) {
String value = tm.get(key);
System.out.println(key.getName() + "---" + key.getAge() + "---" + value);
}
}
}
需求:
假设HashMap集合的元素是ArrayList。有3个。
每一个ArrayList集合的值是字符串。
元素我已经完成,请遍历。
结果:
三国演义
吕布
周瑜
笑傲江湖
令狐冲
林平之
神雕侠侣
郭靖
杨过
package hashmao2;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
public class HashMapIncludeArrayListTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
HashMap<String, ArrayList<String>> hashMap = new HashMap<String, ArrayList<String>>();
ArrayList<String> arrayList1 = new ArrayList<String>();
arrayList1.add("吕布");
arrayList1.add("周瑜");
hashMap.put("三国演义", arrayList1);
ArrayList<String> arrayList2 = new ArrayList<String>();
arrayList2.add("令狐冲");
arrayList2.add("林平之");
hashMap.put("笑傲江湖", arrayList2);
ArrayList<String> arrayList3 = new ArrayList<String>();
arrayList3.add("郭靖");
arrayList3.add("黄蓉");
hashMap.put("射雕英雄传", arrayList3);
Set<String> set = hashMap.keySet();
for (String key : set) {
System.out.println(key);
// 通过key找ArrayList<String> value
ArrayList<String> value = hashMap.get(key);
for (String string : value) {
System.out.println("\t " + string);
}
}
}
}
HashMap里面嵌套HashMap
代码示例
package hashmap2;
import java.util.HashMap;
public class HashMapicludeHashMapDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
HashMap<Student,String> hashMap=new HashMap<Student,String>();
hashMap.put(new Student("张三",23),"北京");
hashMap.put(new Student("李四",24),"北京");
hashMap.put(new Student("王五",25), "上海");
hashMap.put(new Student("赵六",26), "广州");
hashMap.put(new Student("钱七",27), "深圳");
HashMap<Student, String> hashMap2=new HashMap<Student,String>();
hashMap2.put(new Student("唐僧",1023), "长安");
hashMap2.put(new Student("孙悟空",1024), "花果山");
hashMap2.put(new Student("猪八戒",1025), "高老庄");
hashMap2.put(new Student("沙和尚",1026), "流沙河");
//蒂尼双列大集合
HashMap<HashMap<Student, String>, String> hm=new HashMap<HashMap<Student,String>, String>();
hm.put(hashMap, "闲杂人等");
hm.put(hashMap2, "83版西游记");
for (HashMap<Student, String> hMap:hm.keySet()) {
String value=hm.get(hMap);
System.out.println(value);
for (Student key:hMap.keySet()) {
String value2=hMap.get(key);
System.out.println("\t"+key.getName()+"---"+key.getAge()+"----"+value2);
}
}
}
}
面试题:
HashMap集合和Hashtable的区别?
共同点:都是map接口的实现类,都是基于哈希表的实现类
HashMap集合是线程不安全的类,不同步,执行效率高(允许键和值是null的)
Hashtable集合线程安全的类,同步,执行效率低(不允许有null键和null值)
线程安全的类:
StringBuffer :字符串缓冲区
Vector :List集合
Hashtable :Map集合
代码示例
package hashmap;
import java.util.Hashtable;
public class HashtableDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
Hashtable<String, String> hm = new Hashtable<String, String>();
hm.put("你好", "java");
hm.put("你好", "j");
hm.put("你好", "a");
hm.put("你好", "v");
// hm.put("你好","a");
// hm.put("hello", null);//NullPointerException
// hm.put(null, "world") ;//NullPointerException
System.out.println(hm);
}
}
需求:
字符串:比如: 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集合即可
代码示例
package hashmap;
import java.util.HashMap;
import java.util.Scanner;
import java.util.Set;
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String string = in.nextLine();
HashMap<Character, Integer> hashMap = new HashMap<Character, Integer>();
char[] cs = string.toCharArray();
for (char c : cs) {
Integer integer = hashMap.get(c);// 通过键c找值integer
if (integer == null) {
// 还没有存储过
hashMap.put(c, 1);
} else { // <a,2> get(a)==2 integer++=3 put(a,3) <a,3>
// <b,4> get(b)==4 integer++=5 put(b,5) <b,5>
// integer不为null,则说明已经存储过了,再进行存储的话则个数加一
integer++;
hashMap.put(c, integer);
}
}
// 创建一个字符串缓冲区对象
StringBuffer stringBuffer = new StringBuffer();
Set<Character> set = hashMap.keySet();
// 遍历HashMap集合,将相应的key和value添加到StringBuffer中
for (Character key : set) {
Integer value = hashMap.get(key);
stringBuffer.append(key).append("(").append(value).append(")");
}
String string2 = stringBuffer.toString();
System.out.println("输入的字符串在集合中的存储形式为:" + string2);
}
}
Collection和Collections的区别:
Collection:顶层次单列集合的根接口,它是一个集合,是一个接口
Collections:对集合进行操作的工具类,有一些功能:随机置换,集合里面的二分查找,将集合的元素进行反转
public static <T> int binarySearch(List<T> list, T key)集合的二分查找
static T max(Collection coll):获取集合中的最大值
public static void reverse(List<?> list):将集合中的元素顺序反转
public static void shuffle(List<?> list):将集合中的元素打乱
public static void sort(List<T> list)
代码示例
package collections;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CollectionsDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
List<Integer> list = new ArrayList<Integer>();
list.add(44);
list.add(32);
list.add(23);
list.add(54);
list.add(65);
list.add(34);
list.add(76);
list.add(78);
list.add(48);
list.add(42);
list.add(99);
list.add(666);
System.out.println(list);
Collections.sort(list);
System.out.println(list);
int index = Collections.max(list);
System.out.println(index);
Collections.reverse(list);
System.out.println(list);
Collections.shuffle(list);
System.out.println(list);
}
}
public static void sort(List<T> list ,Comparator comparator):可以使用比较器进行排序
package collections;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import hashmap2.Student;
public class CollectionsDemo2 {
public static void main(String[] args) {
List<Student> list = new ArrayList<Student>();
Student s1 = new Student("高圆圆", 28);
Student s2 = new Student("唐嫣", 28);
Student s3 = new Student("刘诗诗", 28);
Student s4 = new Student("文章", 30);
Student s5 = new Student("马伊琍", 39);
Student s6 = new Student("高圆圆", 28);
// 添加到集合中
list.add(s1);
list.add(s2);
list.add(s3);
list.add(s4);
list.add(s5);
list.add(s6);
Collections.sort(list, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
// TODO Auto-generated method stub
// return 0;
int num1 = o1.getAge() - o2.getAge();
int num2 = num1 == 0 ? o1.getName().compareTo(o2.getName()) : num1;
return num2;
}
});
for (Student student : list) {
System.out.println(student.getName() + "-----" + student.getAge());
}
}
}