一、Map

(1)独立的接口,成对地存储数据,每一对称为键值对
(2)键不能重复,如果重复了,则后添加的value会覆盖先添加的value
(3)值是可以重复的
(4)无序
下面是Map常用的几个操作(必记!)

  • 添加:
V put(K key, V value) 
 V putIfAbsent(K key, V value)
 void putAll(Map<? extends K,? extends V> m)
  • 删除:
V remove(Object key) 
 boolean remove(Object key, Object value)
 void clear()
  • 修改:
V replace(K key, V value)
 boolean replace(K key, V oldValue, V newValue)
 void replaceAll(BiFunction<K, V, V> biFunction)
  • 获取:
V get(Object key) 
  V getOrDefault(Object key, V defaultValue)
  Set<K> keySet() 
  Set<Map.Entry<K,V>> entrySet() 
  int size() 
  Collection<V> values()
  • 判断:
boolean isEmpty() 
 boolean containsKey(Object key) 
 boolean containsValue(Object value)

下面来看看怎么使用吧

import java.util.*;
class Demo1 
{
	public static void main(String[] args) 
	{

       Map<String,String> map =new HashMap<>();
       // V put(K key, V value) 
	   String value = map.put("name","lisi");//返回的是上一次添加的键相同的键值对儿的值
	   sop(value);//null
	   value = map.put("name","zhangsan");
	   sop(value);//"lisi"

	   sop(map);

      //V putIfAbsent(K key, V value)
	  String v  = map.putIfAbsent("name","xiaoming");//如果相同键的键值对儿,则不添加
      sop(map);
      //void putAll(Map<? extends K,? extends V> m)
	  Map<String,String> map2 =new HashMap<>();
	  map2.put("address","beijing");
	  map2.put("age","20");

	  map.putAll(map2);
	  sop(map);

	   //V remove(Object key) 
	   //String vv = map.remove("age");
	   //sop(vv);
       //boolean remove(Object key, Object value)
       boolean boo = map.remove("age","18");//仅当键和值完全一致时才会删除
	   sop(boo);//false
       //void clear() 
	   //map.clear();
	   //sop(map);


	   //V replace(K key, V value)  修改键对应的值
       String zhi = map.replace("address","shenzhen");//返回的是被替换的值
	   sop(zhi);
       //boolean replace(K key, V oldValue, V newValue) //完全一致的键值对儿的值被修改为新的值
       boo = map.replace("address","shenzhen","shanghai");
	   sop(boo);
       //void replaceAll(BiFunction<K, V, V> biFunction) 返回的值替换了键值对儿原有的值,键不会被替换
	   map.replaceAll((t,u) ->{
		  if("name".equals(t))
			  return u+"hehe";
		  return u;
	   });
	   sop(map);

	  //V get(Object key) 根据键获取值
	  String zhi2=map.get("address");
	  sop(zhi2);

      //V getOrDefault(Object key, V defaultValue) 
	  String defaults = map.getOrDefault("height","160");//键不存在时,使用默认值,存在时,返回键的值
	  sop(defaults);

	  //int size()  返回对儿数
	  sop(map.size());
      //Collection<V> values() 得到集合中所有的值
	  Collection<String> vs = map.values();
	  sop(vs);

	  //boolean isEmpty() 
	  sop(map.isEmpty());
      //boolean containsKey(Object key) 
      sop(map.containsKey("age"));
      //boolean containsValue(Object value) 
	  sop(map.containsValue("88"));
	}

	public static void sop(Object obj)
	{
		System.out.println(obj);
	}

}

二、Map四种遍历方式

class Demo2 
{
	public static void main(String[] args) 
	{
		//Map集合的遍历
		Map<String,String> map = new HashMap<>();
		map.put("name","lisi");
		map.put("age","18");
		map.put("address","shenzhen");
		
		//第一种
		//Set<Map.Entry<K,V>> entrySet() 
		Set<Map.Entry<String,String>> en = map.entrySet();
		/*
		Iterator<Map.Entry<String,String>> ite=en.iterator();
		while(ite.hasNext())
		{
			Map.Entry<String,String> entry = ite.next();
			String key = entry.getKey();
			String value = entry.getValue();
			sop(key+"="+value);
		}*/
		
		//第二种
		for(Map.Entry<String,String> ent:en)
		{
			String k = ent.getKey();
			String v = ent.getValue();
            sop(k+"="+v);
		}
		
		//第三种
		map.forEach((t,u) ->System.out.println(t+"="+u));

		//第四种
       /*
        //Set<K> keySet() 
		Set<String> keys = map.keySet();
		Iterator<String> ite=keys.iterator();
		while(ite.hasNext())
		{
			String key=ite.next();//得到键
			String value = map.get(key);//根据键获取值
			sop(key+"="+value);
		}

		*/
	}

	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}

下面是Set<Map.Entry<K,V>> entrySet() 底层示意图

java map放去数组 java map value为数组_java map放去数组

什么情况下使用Map?存储的数据时键值对的关系的时候
HashMap保证键值对不重复的原理和HashSet一样:int hashCode() 和 boolean equals(Object obj)

判断集合中是否包含该键,还是依据int hashCode() 和 boolean equals(Object obj)
如put()、remove()、containsKay()方法都需要判断是否包含该键。
下面给出的实例实现了Comparable接口和重写了hashCode()、equals()方法:

import java.util.*;
class Student implements Comparable<Student>
{
	private String name;
	private int age;

	Student(){}

	Student(String name,int age)
	{
		this.name=name;
		this.age=age;
	}

	public int compareTo(Student stu)
	{
		int num = this.age-stu.age;
		return num==0?this.name.compareTo(stu.name):num;
	}

	public int hashCode()
	{
		return name.hashCode()+age*36;
	}
	public boolean equals(Object obj)
	{
		if(!(obj instanceof Student))
			throw new ClassCastException("类型不对");

		Student stu=(Student)obj;
        return this.name.equals(stu.name) && this.age==stu.age;
	}

	public int getAge()
	{
		return age;
	}
	public String getName()
	{
		return  name;	
	}

	public String toString()
	{
		return name+","+age;
	}

}
class Demo3 
{
	public static void main(String[] args) 
	{
       //什么情况下使用Map?存储的数据是键值对儿的关系的时候
	   //每个学生对应一个住址
	   //HashMap保证键不重复的原理和HashSet一样:int hashCode()  boolean equals(Object obj)
	   Map<Student,String> map =new HashMap<>();

       map.put(new Student("lisi",23),"深圳");
	   map.put(new Student("zhangsan",20),"北京");
	   map.put(new Student("wangwu",25),"哈尔滨");
	   map.put(new Student("xiaoming",21),"连云港");
	   map.put(new Student("lihua",22),"杭州");
	   map.put(new Student("xiaoming",21),"大连");//覆盖掉相同键对应的值

	   //实现需求:姓名年龄相同的认为是同一个键

       Set<Map.Entry<Student,String>> stus = map.entrySet();
	   Iterator<Map.Entry<Student,String>> ite=stus.iterator();
	   while(ite.hasNext())
		{
			Map.Entry<Student,String> en=ite.next();
			Student key = en.getKey();
			String value = en.getValue();
			System.out.println(key+"="+value);
		}

		map.remove(new Student("xiaoming",21));//判断集合中是否存在该键,还是依据int hashCode()  boolean equals(Object obj)方法
        map.forEach((t,u) -> System.out.println(t+"="+u));
		System.out.println(map.containsKey(new Student("lisi",23)));
	}
}

我们再新建一个文件,重写一下Comparator接口,接着看看Compare()方法

import java.util.*;
class ComByName implements Comparator<Student>
{
   public int compare(Student stu1,Student stu2){
	   
	   int n = stu1.getName().compareTo(stu2.getName());
	   return n==0?stu1.getAge()-stu2.getAge():n;
   }
}
class Demo4 
{
	public static void main(String[] args) 
	{
		//TreeMap:TreeSet,排序,根据键排序,保证键唯一的原理:compareTo方法或compare方法的返回值是否为0,返回值为0认为是相同的键
       ComByName byName = new ComByName();
	   Map<Student,String> map =new TreeMap<>(byName);//使用了Comparator,Comparable失效

       map.put(new Student("lisi",23),"深圳");
	   map.put(new Student("zhangsan",20),"北京");
	   map.put(new Student("wangwu",25),"哈尔滨");
	   map.put(new Student("xiaoming",21),"连云港");
	   map.put(new Student("lihua",22),"杭州");
	   map.put(new Student("xiaoming",21),"大连");//覆盖掉相同键对应的值      

	   System.out.println(map);
	}
}

TreeMap:TreeSet,排序,根据键排序,保证键唯一的原理:compareTo()方法或compare方法返回值是否为0,返回值为0则认为是相同的键

三、数组转集合

java map放去数组 java map value为数组_java map放去数组_02

(1)数组转集合不能添加或删除数据,否则会抛出UnsupportedOperationException
(2)数组转集合是为了使用集合中丰富的方法
(3)转换成List后,集合中只有一个对象,把整个数组存在了集合中

import java.util.*;
class Demo6 
{
	public static void main(String[] args) 
	{
		//数组转集合  static <T> List<T> asList(T... arr)  了解

        String[] arr={"bigdata","java","html"};
        
		List<String> list = Arrays.asList(arr);
         
        //list.add("hehe");//UnsupportedOperationException 数组转集合不能添加或删除数据

        //数组转集合是为了使用集合的丰富的方法
		Iterator<String> ite=list.iterator();
		while(ite.hasNext())
		{
			System.out.println(ite.next());
		}

		System.out.println(list.contains("java"));

		int[] b={4,5,6};

		List<int[]> list2=Arrays.asList(b);

		System.out.println(list2.size());//1  集合中只有一个对象 把整个数组存在了集合中

		System.out.println(list2.get(0).length);
	}
}

四、集合转数组

java map放去数组 java map value为数组_java map放去数组_03


给定数组的长度大于等于集合中元素的个数,那么直接使用给定的数组

给定数组的长度小于集合中元素的个数,那么会再创建一个长度和集合元素个数相同的数组

import java.util.*;
class Demo7 
{
	public static void main(String[] args) 
	{
		//集合转数组  <T> T[] toArray(T[] a)  

		List<String> list = new ArrayList<>();
		list.add("hello");
		list.add("world");
		list.add("hai");
        
		//给定数组的长度大于等于集合中元素的个数,那么直接使用给定的数组
		//给定数组的长度小于等于集合中元素的个数,那么会再创建一个长度和集合元素个数相同的数组
		String[] arr = list.toArray(new String[list.size()]);

		//但不希望用户随意增删数据的时候,使用集合转数组

		System.out.println(arr.length);
	}
}

五、集合的工具类:Collections

import java.util.*;
class Demo8 
{
	public static void main(String[] args) 
	{
		//集合的工具类:Collections

       //static <T> boolean addAll(Collection<? super T> c, T... elements)  

	   List<Integer> list = new ArrayList<>();

       Collections.addAll(list,5,6,7,8,9,19);

	   //static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)  
       //集合中的元素所属的类必须实现了Comparable接口
       Integer max = Collections.max(list);
	   System.out.println(max);

	   //static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp)  
       Integer max2=Collections.max(list,(t1,t2) -> t2-t1);
	   System.out.println(max2);

	   Integer max3=Collections.max(list,Collections.reverseOrder((t1,t2) -> t2-t1));
       System.out.println(max3);

	   //static <T> Comparator<T> reverseOrder() 
	   //static <T> Comparator<T> reverseOrder(Comparator<T> cmp)  得到和给定的比较方式相反的比较方式

	   Collections.reverse(list);//集合元素倒序
	   System.out.println(list);

	   Collections.swap(list,0,3);//交换
	   System.out.println(list);

	   Collections.shuffle(list);//随机打乱元素顺序
	   System.out.println(list);


	   List<String> list2 = new ArrayList<>();
	   list2.add("hello");
	   list2.add("ahello");
	   list2.add("zhello");

	   //Collections.sort(list2);
	   //System.out.println(list2);

	   Collections.sort(list2,Collections.reverseOrder());//得到和默认比较方式相反的比较方式Comparator
	   System.out.println(list2);

	   List<String> list3 = new ArrayList<>();
       Collections.addAll(list3,"","","");

	   Collections.copy(list3,list2);//只负责拷贝数据,不负责分配空间
	    System.out.println(list3);

       System.arraycopy(arr1,0,arr2,1,5);//只负责拷贝数据,不负责分配空间

	}
}

六、LinkedHashSet、LinkedHashMap

LinkedHashSet使用链表+哈希表的数据结构,实现了有序,对象不能重复。LinkedHashMap同理。
下面是几个基本操作,要会

import java.util.*;
class Demo9 
{
	public static void main(String[] args) 
	{
		LinkedHashSet<String> linkedHashSet=new LinkedHashSet<>();
        linkedHashSet.add("hehe");
		linkedHashSet.add("hehe");
		linkedHashSet.add("haha");
		linkedHashSet.add("xixi");

		System.out.println(linkedHashSet);//使用链表+哈希表的数据结构,实现了有序,对象不能重复


		LinkedHashMap<String,String> linkedHashMap =new LinkedHashMap<>();
        linkedHashMap.put("name","zhangsan");
		linkedHashMap.put("age","23");
		linkedHashMap.put("address","shanghai");

		System.out.println(linkedHashMap);

		//HashTable :jdk1.0  线程安全的 实现了Map接口

		//如何得到多线程安全的集合对象
		ArrayList list = Collections.synchronizedList(new ArrayList());

		HashSet hs = Collections.synchronizedSet(new HashSet());

		HashMap map = Collections.synchronizedMap(new HashMap());
	}
}

七、HashTable

jdk1.0开始有的元老,线程安全,实现了Map接口

问题:那List、HashSet、HashMap如何得到多线程安全的对象?
使用synchronized,见上面代码(有疑问就查阅API)。

八、Properties

是一个Map集合,因为父类时HashTable

import java.util.*;
class Demo10 
{
	public static void main(String[] args) 
	{
		//Properties 是一个Map集合,因为父类是HashTable,只能存放属性,属性列表中的每个键及其对应的值都是一个字符串
		//Properties 的键和值固定都是String的

        Properties proper = System.getProperties();//把所有的系统属性存储在一个Map集合中了

		System.out.println(proper);

		//Set<String> stringPropertyNames()  得到所有的属性名,其实就是得到所有的键

		Set<String> keys = proper.stringPropertyNames();

		for(String key:keys)
		{
			//根据键获取值 String getProperty(String key)  
			String value = proper.getProperty(key);
			System.out.println(key+"="+value);
		}
        //覆盖了相同键的键值对儿的值,不是修改系统属性,集合在内存中,在内存中修改
		proper.setProperty("user.country","USA");//Object setProperty(String key, String value)  等价于put方法的功能

		
        String v = proper.getProperty("user.country");
		System.out.println(v);

		proper=null;

		Properties pro = System.getProperties();
		System.out.println(pro);
	}
}