* 面试题:
Map和Collection集合的区别?
* Collection集合只能存储一种类型的元素,----->理解为 "单身" 11.11 光棍
* Collection集合的Set的子实现类 hashSet,TreeSet和Map有关系
* Map集合:存储的是键值对,一个键对应一个值(值是可以重复的),针对键有效,跟值无关! 理解为("夫妻对")
* HashMap,TreeMap
map
什么是Map。在数组中我们是通过数组下标来对其内容索引的,而在Map中我们通过对象来对对象进行索引,用来索引的对象叫做key,其对应的对象叫做value。这就是我们平时说的键值对。
通过键----->查询值
Map集合的特点,存储的键值对(键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。)
键如果在Map出现第一次,返回值null,如果键重复了,后面出现的值会将前面的值覆盖掉,返回结果是以前的值
//System.out.println("put():"+map.put("文章","马伊琍")) ;
//System.out.println("put():"+map.put("文章","姚笛")) ;//put():马伊琍
Map<String, String> map = new HashMap<String, String>();
map.put("邓超", "孙俪") ;
map.put("周杰伦", "昆凌") ;
map.put("刘恺威", "杨幂") ;
//删除
// V remove(Object key) :删除指定的键
System.out.println("remove():"+map.remove("邓超"));// remove():孙俪 //返回当前键对应的值
// map.clear(); //暴力删除 (慎用)// {}
//判断功能
//boolean containsKey(Object key) :判断是否包含指定的键
System.out.println("containsKey():"+map.containsKey("文章"));
System.out.println("containsKey():"+map.containsKey("高圆圆"));
//是否包含值 //containsKey():false //containsKey():true
//boolean isEmpty():判断集合是否为空
System.out.println("isEmpty():"+map.isEmpty());//isEmpty():false
//public int size():
System.out.println("size():"+map.size());//size():3
//get(Object key) :根据键获取值
System.out.println("get():"+map.get("周杰伦"));//get():昆凌
System.out.println("get():"+map.get("文章")); //不存在键返回null //get():null
//输出Map集合
System.out.println("map:"+map); //{邓超=孙俪, 周杰伦=昆凌, 高圆圆=赵又廷, 刘恺威=杨幂}
}
//map集合遍历方法(两种)
Map<String,String> map = new HashMap<String,String>();
map.put("02","zhangsan2");
map.put("03", "zhangsan3");
map.put("01", "zhangsan1");
map.put("04", "zhangsan4");
// 第一种:(推荐)Set<K> keySet() :获取所有的键的集合
//先获取map集合的所有键的set集合,keySet()---->get()方法获取对应键的值;
//Set<String>相当于返回值类型,此相当于Set集合加上了泛型,类型为String,set相当于变量名
Set<String> set = map.keySet() ;
//增强for遍历
for(String key: set) {
//通过键获取值
String value = map.get(key) ;
System.out.println(key+"="+value);
}
//第二种:Set<Map.Entry<K,V>> entrySet() :获取键值对象
将map集合中的映射关系存入到set集合中,这个关系的数据类型为:Map.Entry
Map.Entry接口
此接口在java.util包中,其实Entry也是一个接口,它是Map接口中的一个内部接口 ,getKey()和getValue是接口Map.Entry<K,V>中的方法,返回对应的键和对应的值
//获取键值对对象
Set<Map.Entry<String, String>> entrySet = map.entrySet() ;
//遍历所有的键值对
for(Map.Entry<String, String> entry: entrySet) {
//K getKey():获取键
// V getValue():获取值
String key = entry.getKey() ;
String value = entry.getValue() ;
System.out.println(key+"---"+value);
}
//Map.Entry的剖析和getKey(),getValue()的由来:
interface Map{
//此内部接口的特点是静态的,而且是对外提供访问的
public static interface Entry{
//因为具体情况要视情况而定,所以是抽象的,具体由子类来实现
public abstract Object getKey();
public abstract Object getValue();
}
}
abstract class HashMap implements Map{
//内部类实现Map.Entry
abstract class Hahs implements Map.Entry{
public Object getKey(){}
public Object getValue(){}
}
常见问题:
Entry是接口 ,但是为什么不定义定义在外面呢?
原因:
Entry代表的是映射关系,先有Map集合,才有的映射关系,所以它是Map集合内部的事物,因此将Entry定义为
在Map的内部集合,可以直接访问Map集合中的元素
在API文档中有 public static interface Map.Entry<K,V> 其中被static静态修饰,只有接口在
成员位置上才能加静态修饰符 ,说明其是内部接口
keySet()取值方式示例图
entrySet()取值方式示例图:
HashMap
HashMap集合:底层基于哈希表,不能保证顺序恒久不变
//创建一个HashMap集合对象
HashMap<Integer, String> hm = new HashMap<Integer, String>();
//添加元素
hm.put(1, "马云") ;
hm.put(3, "马化腾") ;
hm.put(4, "裘波君") ;
hm.put(6, "雷军") ;
hm.put(3, "王健林") ;
//遍历
Set<Integer> set = hm.keySet() ;
for(Integer key :set) {
String value = hm.get(key) ;
System.out.println(key+"---"+value);
}
1---马云
3---王健林
4---裘波君
6---雷军
```java
//创建HashMap集合对象
HashMap<String, Student> map = new HashMap<String, Student>() ;
//创建几个学生对象
//Student类省略。。。。。注意重写equal、hashcode
Student s1 = new Student("里皮", 70) ;
Student s2 = new Student("瓜迪奥拉", 50) ;
Student s3 = new Student("扎叔", 60) ;
Student s4 = new Student("穆里尼奥", 65) ;
Student s5 = new Student("文章", 36) ;
//添加元素
map.put("it001", s1);//不能写成map.put(s1),必须是(k,v)格式
map.put("it002", s2);
map.put("it003", s3);
map.put("it004", s4);
map.put("it002", s5);
//此处it002会充当key,s5与s2的key相同,s5的内容会覆盖s2的(文章替代瓜迪奥拉)
//遍历
Set<String> set = map.keySet() ;
for(String key:set) {
//通过键获取值
Student value = map.get(key) ;
System.out.println(key+"---"+value.getName()+"---"+value.getAge());
}
/*it004---穆里尼奥---65
it003---扎叔---60
it002---文章---36
it001---里皮---70*/
HashMap<Student, String> map = new HashMap<Student, String>() ;
//创建几个学生对象
Student s1 = new Student("里皮", 70) ;
Student s2 = new Student("瓜迪奥拉", 50) ;
Student s3 = new Student("扎叔", 60) ;
Student s4 = new Student("穆里尼奥", 65) ;
Student s5 = new Student("里皮", 68) ;
Student s6 = new Student("穆里尼奥", 65) ;
//添加元素
map.put(s1, "9527") ;
map.put(s2, "9809") ;
map.put(s3, "9528") ;
map.put(s4, "9529") ;
map.put(s5, "9630") ;
map.put(s6, "9270") ;
//遍历
Set<Student> set = map.keySet() ;
for(Student key :set) {
String value = map.get(key) ;
System.out.println(key.getName()+"---"+key.getAge()+"---"+value);
}
/*
瓜迪奥拉---50---9809
扎叔---60---9528
穆里尼奥---65---9270
里皮---68---9630
里皮---70---9527
//整个(里皮,70)充当一个key,与(里皮,70)key不一致,不会替换(里皮,68)
*/
* LinkedHashMap
- 哈希表和链接列表实现,具有可预知的迭代顺序
- 哈希表:元素唯一
- 链表:有序性
import java.util.LinkedHashMap;
import java.util.Properties;
import java.util.Set;
public class LinkedHashMapDemo {
public static void main(String[] args) {
//创建一个LinkedHashMap集合
LinkedHashMap<String, String> link = new LinkedHashMap<String, String>() ;
//添加元素
link.put("hello", "你好") ;
link.put("hello", "嘞吼") ;
link.put("world", "世界") ;
link.put("java", "爪哇") ;
link.put("java", "爪哇2") ;
//遍历
Set<String> set = link.keySet() ;
for (String key : set) {
String value = link.get(key) ;
/*
* hello----嘞吼
world----世界
java----爪哇2
* */
System.out.println(key+"----"+value);
}
}
}
hello----嘞吼
world----世界
java----爪哇2
TreeMap
import java.util.Comparator;
import java.util.Set;
import java.util.TreeMap;
public class TreeMapDemo {
public static void main(String[] args) {
//创建一个TreeMap集合对象
//TreeMap--->底层红黑树结构 public TreeMap(Comparator<E> comparator)
TreeMap<Student, String> tm = 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("潘安", 28) ;
Student s2 = new Student("柳下惠", 35) ;
Student s3 = new Student("唐伯虎", 35) ;
Student s4 = new Student("燕青", 26) ;
Student s5 = new Student("李白", 38) ;
Student s6 = new Student("唐伯虎", 35) ;
//添加元素
tm.put(s1, "元朝") ;
tm.put(s2, "明朝") ;
tm.put(s3, "明朝") ;
tm.put(s4, "宋朝") ;
tm.put(s5, "唐朝") ;
tm.put(s6, "宋朝") ;
//遍历
Set<Student> set = tm.keySet() ;
for(Student key:set) {
String value = tm.get(key) ;
System.out.println(key.getName()+"---"+key.getAge()+"---"+value);
}
}
}
//Student类
package com.qianfeng.map_05;
public class Student {
private String name ;
private int age ;
//alt+shift+s--->o
public Student() {
super();
}
//alt+shift+s--->c
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
//alt+shift+s--->r
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//toString()
alt+shift+s--->s
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
输出结果:
燕青---26---宋朝
潘安---28---元朝
唐伯虎---35---宋朝
柳下惠---35---明朝
李白---38---唐朝
HashMap与TreeMap区别:
(1)HashMap(): 构建一个空的哈希映像
(2)HashMap(Map m): 构建一个哈希映像,并且添加映像m的所有映射
(3)HashMap(int initialCapacity): 构建一个拥有特定容量的空的哈希映像
(4)HashMap(int initialCapacity, float loadFactor): 构建一个拥有特定容量和加载因子的空的哈希映像
TreeMap:基于红黑树实现。TreeMap没有调优选项,因为该树总处于平衡状态。
(1)TreeMap():构建一个空的映像树
(2)TreeMap(Map m): 构建一个映像树,并且添加映像m中所有元素
(3)TreeMap(Comparator c): 构建一个映像树,并且使用特定的比较器对关键字进行排序
(4)TreeMap(SortedMap s): 构建一个映像树,添加映像树s中所有映射,并且使用与有序映像s相同的比较器排序
两种常规Map性能
HashMap:适用于在Map中插入、删除和定位元素。
Treemap:适用于按自然顺序或自定义顺序遍历键(key)。
HashMap通过hashcode对其内容进行快速查找,而 TreeMap中所有的元素都保持着某种固定的顺序,如果你需要得到一个有序的结果你就应该使用TreeMap(HashMap中元素的排列顺序是不固定的)。
HashMap 非线程安全 TreeMap 非线程安全
HashMap和Hashtable的区别?
-
HashMap:底层是哈希表结构,保证元素唯一,不能保证顺序恒久不变
-
它存储null键 null值----->线程不安全,不同步—执行效率高
-
Hashtable<K,V>:不允许null键和null值出现 底层哈希表实现
-
线程安全,同步----->执行效率低
-
Hashtable存在子类:Properties 属性集合类 唯一特点:键和值都是String
-
线程安全的类:
-
StringBuffer,Vector,Hashtable
-
List,Set,Map等接口是否都继承子Map接口
Collection集合单列集合的根接口
List和Set属于Collection子接口
Map 存储键值元素的根接口
HashMap,TreeMap