一、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() 底层示意图
什么情况下使用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则认为是相同的键
三、数组转集合
(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);
}
}
四、集合转数组
给定数组的长度大于等于集合中元素的个数,那么直接使用给定的数组
给定数组的长度小于集合中元素的个数,那么会再创建一个长度和集合元素个数相同的数组
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);
}
}