------- android培训、java培训、期待与您交流! ----------
————————————————————————————————————————————
Map集合:它存储的是键值对,其中键必须保证唯一性,值允许重复。Map集合没有自身特有的迭代器,它的元素取出是通过将键或键值对放入Set集合中,利用Set集合中的迭代器取出的。Map是双列集合,Collection是单列集合。
Map接口中定义了该体系通用的方法。
1.添加
V put(K key, V value)
void putAll(Map<? extends K,? extends V>m)
注意put与add的不同:put时,如果key已经存在,则新存入的值覆盖原来的值,并把原来的值作为方法的返回值;add时,如果该元素已经存在,则不能存入集合,方法返回值为false,如果存在,则存入集合,方法返回值为true。
2.删除
clear()
V remove(Object key)
3.判断
boolean containsKey(Object key)
boolean containsValue(Object value)
boolean isEmpty()
4.获取
V get(Object key)
int size()
Collection<V> values()
Set<Map.Entry<K,V>>entrySet()
Set<K> keySet()
import java.util.Collection; import java.util.HashMap; import java.util.Map; class MapDemo { public static void main(String[] args) { Map<String,String> map = new HashMap <String,String>(); System.out.println("put:"+map.put("01","zhangsan01"));//结果为null System.out.println("put:"+map.put("01","wangwu"));//结果我zhangsan01 /* put如果存入了已经存在的键,则新键值会覆盖旧键值,并将旧键值返回;put存入一个未存在的键时,会返回null。 */ map.put("02","zhangsan02"); map.put("03","zhangsan02"); map.put(null,null); System.out.println("containsKey:"+map.containsKey("022")); //System.out.println("remove:"+map.remove("02")); System.out.println("get:"+map.get("023")); map.put("04","null"); System.out.println("get:"+map.get("04")); //可以通过get方法的返回值来判断一个键是否存在。通过返回null来判断。(毕老师这点讲的是不是有问题?) //获取map集合中的值 Collection <String> coll =map.values(); System.out.println(coll); System.out.println(map); } } /* 既然hashMap可以存放null键null值,那么通过get方法返回null,应该不能判断该键是不是存在,因为可能出现有键值为空的情况;这时就要用containsKey()方法来判断了 */
Map
|---Hashtable<K,V>:底层是哈希表数据结构,不可以存入null键null值,该集合是同步的。JDK1.0,效率低。,
|---HashMap<K,V>:底层是哈希表数据结构,允许存入null键null值,该集合是不同步的。JDK1.2,效率高。
|---TreeMap<K,V>:底层是二叉树结构,线程不同步,可以用于给Map集合中键进行排序。
和Set很像,其实Set底层就是使用了Map集合。
/* map集合的两种取出方式: 1.Set<K> keySet;将map中的所有的键存入到Set集合,因为set具有迭代器。 所以可以迭代方式取出所有的键,再根据get方法,获取每一个键对应的值。 Map集合的取出原理:将Map集合转成Set集合,再通过迭代器取出。 2.Set<Map.Entry<K,V>> entrySet:将Map集合中的映射关系存入到了Set集合中, 而这个关系的数据类型就是:Map.Entry. */ import java.util.HashMap; import java.util.Iterator; import java.util.Set; import java.util.Map; class MapDemo2 { public static void main(String[] args) { Map <String,String> map = new HashMap<String ,String>(); map.put("01","zhangsan01"); map.put("02","zhangsan02"); map.put("03","zhangsan03"); map.put("04","zhangsan04"); System.out.println(map); System.out.println("-------------"); //Map元素取出的方式一(EntrySet):将Map集合中的映射关系取出,存入到Set集合中。 Set<Map.Entry<String , String>> entrySet = map.entrySet(); System.out.println(entrySet); System.out.println("-------------"); Iterator<Map.Entry<String , String>> it = entrySet.iterator(); while(it.hasNext()) { Map.Entry<String,String> me = it.next(); String key = me.getKey(); String value = me.getValue(); System.out.println(me); System.out.println("key:"+key+",value="+value); } //元素取出的方式二(KeySet) /* //先获取map集合的所有键的Set集合。 Set<String> keySet = map.keySet(); //有了Set集合,就可以获取机迭代器。 Iterator<String> it = keySet.iterator(); while(it.hasNext()) { String key = it.next(); String value = map.get(key); System.out.println("key:"+key+",value="+value); } */ } } /* Map.Entry 其实Entry也是一个接口,他是Map接口中的一个内部接口。如下: interface Map { public static interface Entry { public abstract Object getKey(); public abstract Object getValue(); } } class HashMap implements Map { class Haha implements Map.Entry { public Object getKey(){} public Object getValue(){} } } */
/* 每一个学生都有对应的归属地 学生Student,地址String 学生属性:姓名,年龄 注意:姓名和年龄相同视为同一个学生 保证学生的唯一性。 1.描述学生 2.定义Map容器,将学生作为键,地址作为值,存入。 3.获取Map集合中的元素。 */ import java.util.*; class MapTest { public static void main(String[] args) { HashMap<Student,String> hm = new HashMap<Student,String>(); hm.put(new Student("lisi1",22),"beijing"); hm.put(new Student("lisi1",22),"shanghai"); hm.put(new Student("lisi3",24),"wuhan"); hm.put(new Student("lisi4",25),"nanjing"); //第一种取出方式:keySet() Iterator<Student> it = hm.keySet().iterator(); while(it.hasNext()) { Student stu = it.next(); String addr = hm.get(stu); System.out.println(stu+".."+addr); } System.out.println("-------------"); //第二种取出方式:entrySet() Set<Map.Entry<Student,String>> entrySet = hm.entrySet(); Iterator<Map.Entry<Student,String>> ite = entrySet.iterator(); while(ite.hasNext()) { Map.Entry<Student,String> me = ite.next(); Student s = me.getKey(); String str = me.getValue(); System.out.println(s+","+str); } } } /* 为什么将复写equals、hashCode方法,并实现comparable接口? 因为,Sutdent有可能存入HashMap中,也有可能存入TreeMap中。 */ class Student implements Comparable<Student> { private String name; private int age; Student(String name,int age) { 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; } public int hashCode() { return name.hashCode()+37*age;//这点要注意 } public boolean equals(Object obj) { if( !(obj instanceof Student)) throw new ClassCastException("类型不匹配"); Student s = (Student) obj; return this.name.equals(s.getName())&&this.age==s.getAge(); } public int compareTo(Student s) { int num = new Integer(this.age).compareTo(new Integer(s.getAge())); if(num == 0) this.name.equals(s.name); return num; } public String toString() { return name+","+age; } }
/* 需求:对学生对象的年龄进行升序排序。 因为数据是以键值对形式存在的,所以要使用可以排序的Map集合,TreeMap。 */ import java.util.*; class StuNameComparator implements Comparator<Student> { public int compare(Student s1,Student s2) { int num = s1.getName().compareTo(s2.getName()); if(num == 0) return new Integer(s1.getAge()).compareTo(s2.getAge()); return num; } } class MapTest2 { public static void main(String[] args) { TreeMap<Student,String> tm = new TreeMap<Student,String>(new StuNameComparator()); tm.put(new Student("lisi1",22),"beijing"); tm.put(new Student("alisi1",23),"shanghai"); tm.put(new Student("alisi1",24),"shanghai"); tm.put(new Student("xlisi3",24),"wuhan"); tm.put(new Student("lisi4",25),"nanjing"); Iterator<Map.Entry<Student,String>> it = tm.entrySet().iterator(); while(it.hasNext()) { Map.Entry<Student,String> me = it.next(); Student stu = me.getKey(); String addr = me.getValue(); System.out.println(stu+","+addr); } } }
/* 练习: ”stdafasdffadf“获取该字符串中的字母出现的次数。 希望打印结果:a(1)c(2)。。。。 通过结果发现,每个字母都有对应的次数 说明字母和次数之间都有映射关系。 注意了,当发现有映射关系时,可以选择Map集合 因为Map集合中存放的就是映射关系。 什么时候使用Map集合呢? 当数据之间存在这个映射关系时,就要先想到Map集合。 我的思路: 1.建立字母为键,类型为char,次数为值,类型为int,的Map,因为字母按顺序打印,所以选用TreeMap 2.将字符串遍历,重复的字符,值++; 3.使用迭代器打印TreeMap集合。 毕老师思路: 1.将字符串转换成字符数组,因为要对每一个字母进行操作。 2.定义一个map集合,因为打印结果的字母有顺序,所以使用TreeMap集合。 3.遍历字符数组。 将每一个字符作为键去查map集合。 如果返回null,将该字母和1存入到map集合。 如果返回不是null,说明该字母在map集合已经存在,并有对应的次数。 那么就获取该次数进行自增,然后将该字母和自增后的次数存入到map集合中,覆盖调用原键所对应的值。 4.将map集合中的数据变成指定的字符串形式返回。 */ import java.util.*; class MapTest3 { public static void main(String[] args) { //String str = myCharCount("adfasdf!!!!!sssasdfas"); String str =charCount("dsadfadfasdf"); System.out.println(str); } //毕老师的方法 public static String charCount(String str) { char [] chs = str.toCharArray(); TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>(); for(int x =0;x<chs.length;x++) { int count =0; char ch = str.charAt(x); if(!(ch>='a'&&ch<='z'|| ch>='A'&&ch<='Z')) continue ; Integer value = tm.get(chs[x]); /* if(value == null) tm.put(chs[x],1); else { value = value+1; tm.put(chs[x],value); } */ if(value!=null) count = value; count++; tm.put(chs[x],count); } StringBuilder sb = new StringBuilder(); Set<Map.Entry<Character,Integer>> entrySet = tm.entrySet(); Iterator<Map.Entry<Character,Integer>>it = entrySet.iterator(); while(it.hasNext()) { Map.Entry<Character,Integer> me = it.next(); Character ch = me.getKey(); Integer value = me.getValue(); sb.append(ch+"("+value+")"); } return sb.toString(); } //我的方法 public static String myCharCount(String str) { String resault=""; TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>(); int count = 0; for(int x =0;x<str.length();x++) { char ch = str.charAt(x); if(!(ch>='a'&&ch<='z'|| ch>='A'&&ch<='Z')) continue ; if(!tm.containsKey(ch)) tm.put(ch,1); else { int num =tm.get(ch)+1; tm.put(ch,num); } } Iterator<Map.Entry<Character,Integer>> it = tm.entrySet().iterator(); while(it.hasNext()) { Map.Entry<Character,Integer> me = it.next(); char letter = me.getKey(); int num = me.getValue(); resault += letter+"("+num+")"; } return resault; } }
Map集合中的值还可以是Map集合,这是Map集合嵌套使用的情况。
/* map扩展知识 map集合使用是因为具备映射关系。 “yureban” “01” “zhangsan” “yureban” “02” "lisi" "jiuyeban" "01" "zhousi" "jiuyeban" "02" "liuwu" 一个学校有多个教室,每个教室都有自己的名字,而一个教室对应多个学生。 */ import java.util.*; class Student1 { private static String id; private String name; Student1(String id,String name) { this.id = id; this.name = name; } public String toString() { return id+":::"+name; } public static void main(String[] args) { Student1 s1 =new Student1("id","name"); id = "1212"; Integer a = Integer.parseInt(id,10); System.out.println(s1.id); System.out.println(a); } } class MapDemo3 { public static void demo() { HashMap<String,List<Student1>> czbk = new HashMap<String,List<Student1>>(); List<Student1> yure = new ArrayList<Student1>(); List<Student1> jiuye = new ArrayList<Student1>(); czbk.put("yuer:",yure); czbk.put("jiuye:",jiuye); yure.add(new Student1("01","zhangsan")); yure.add(new Student1("02","wagnwu")); jiuye.add(new Student1("01","liuqiang")); jiuye.add(new Student1("02","limeng")); Iterator<String> it = czbk.keySet().iterator(); while(it.hasNext()) { String roomName = it.next(); List<Student1> room = czbk.get(roomName); System.out.println(roomName); getInfos(room); } } public static void getInfos(List<Student1> room) { Iterator<Student1> it = room.iterator(); while(it.hasNext()) { System.out.println(it.next()); } } public static void main(String[] args) { demo(); } public static void getStudentInfo(HashMap<String,String> hm) { Iterator<Map.Entry<String,String>> it = hm.entrySet().iterator(); while(it.hasNext()) { Map.Entry<String,String> me = it.next(); String num =me.getKey(); String name = me.getValue(); System.out.println(num+":"+name); } System.out.println(hm); } }
Collections是一个集合工具类,它没有构造方法,所有的成员方法都是静态的。利用它可以实现对集合的一些特殊操作,如排序、二分查找、取最值、反转等。
1、 对List集合进行排序
Collections.sort(list),Collections.sort( list, comparator)。
2、 获取集合的最大值
Collections.sort(collection),Collections.sort(collection,comparator)。
3、 二分查找
binarySearch(List<? extends Comparable<? super T>> list, T key)
binarySearch(List<? extends T> list, T key, Comparator<? super T> c)
4、 填充
fill(list,obj),将集合所有元素都换成obj
5、 替换
replaceAll(List<T> list, T oldVal, T newVal),将集合中出现的所有的某一个值,替换为另一个。
6、 反转
reverse(List<?> list),头变尾,尾变头。
7、随机排列
shuffle(list),应用:洗牌、掷色子。
重点掌握的下边三个方法
1、 reverseOrder:强行逆转比较器的自然顺序或元素的自然顺序。
2、
将集合由线程不安全转为线程安全的
synchronizedCollection
(Collection<T>c)
synchronizedList(List<T>list)
synchronizedMap(Map<K,V>m)
synchronizedSet(Set<T>s)
其原理是:内部封装一个容器,然后定义一个锁,使用该锁同步并封装该容器的所有方法。
import java.util.*; class CollectionsDemo { public static void main(String[] args) { sortDemo(); } public static void sortDemo() { List <String> list = new ArrayList<String>(); list.add("abcdd"); list.add("asdfas"); list.add("saa"); list.add("bbb"); list.add("qt"); list.add("bbb"); sop(list); //排序演示,要排序的元素继承comparable类或者新建一个比较器。 Collections.sort(list,new StrLenComparator()); sop(list); sop("----------sort"); //取最大值演示:要排序的元素继承comparable类或者新建一个比较器。 String max = Collections.max(list,new StrLenComparator()); sop(max); sop("----------max"); //二分查找:必须先是有序集合,前后排序的比较规需要相同,是自然顺序都是自然顺序,是比较器都是比较器。 int index = Collections.binarySearch(list,"kkkk"); //int index = halfSearch(list,"aaaa"); sop(index); sop("----------binarySearch"); /* 我的问题:如果前边排序是用比较器,后来查找的时候没有加比较器,返回值如何? */ //reverse:将集合中的元素反转。 Collections.reverse(list); sop(list); sop("----------reverse"); //swap():交换集合中两个元素的位置 Collections.swap(list,2,5); sop(list); sop("----------swap"); //shufle:使用默认随机源对指定列表进行置换(如洗牌动作、色子) Collections.shuffle(list); sop(list); sop("----------shuffle"); //fill方法:可以将list集合中的所有元素替换成指定元素, //练习:将list集合中的部分元素替换成指定元素。 sop(list); Collections.fill(list,"yyyy"); sop(list); sop("----------fill"); //repalceAll:将集合中的所有的指定元素替换成新元素 Collections.replaceAll(list,"yyyy","00");//其实封装了list.set(index,"00"); sop(list); sop("----------repalceAll"); } //二分法原理。 public static int halfSearch(List<String> list,String key/*,Comparator cmp*/) { int max,min,mid; max =list.size()-1; min = 0; while(min<max) { mid =(max+min)>>1; String str = list.get(mid); int num = str.compareTo(key);//int num = cmp.compare(s1,s2); if(num>0) max =mid -1; else if(num<0) min =mid + 1; else return mid; } return min;//-min-1; } public static void sop(Object obj) { System.out.println(obj); } } class StrLenComparator implements Comparator<String> { public int compare(String s1,String s2) { if(s1.length()>s2.length()) return 1; if(s1.length()<s2.length()) return -1; return s1.compareTo(s2); } }
* Collections.reverseOrder()命令:反转自然顺序或比较器 */ import java.util.*; class StrComparator implements Comparator<String> { public int compare(String s1,String s2) { /*int num =s1.compareTo(s2); if(num>0) return 1; if(num<0) return -1; return num; */ return s2.compareTo(s1); } } class StrLenComparator implements Comparator<String> { public int compare(String s1,String s2) { if(s1.length()>s2.length()) return 1; if(s1.length()<s2.length()) return -1; return s1.compareTo(s2); } } class CollectionsDemo2 { public static void main(String[] args) { orderDemo(); } public static void orderDemo() { TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder( new StrLenComparator())); ts.add("adsdf"); ts.add("afasdf"); ts.add("efsf"); ts.add("bc"); ts.add("e"); Iterator<String> it = ts.iterator(); while(it.hasNext()) { System.out.println(it.next()); } } }
数组工具类:
binarySearch:二分查找数组中的元素。
copyOf:复制数组
copyOfRange:复制数组内的某一段
equals:判断两个数组是否相等。
deeEquals:如果两个指定数组彼此是深层相等的,则返回true。
deeHashCode:基于指定数组的“深层内容”返回哈希码。
deeToString: 返回指定数组“深层内容”的字符串表示形式。
fill:将指定的值分配给指定数组的每个元素。
hashCode:基于指定数组的内容返回哈希码。
sort: 对数组元素进行排序
toString:把数组的元素转化成字符串
重点:Arrays有个asList(T… t)方法,可以把数组转换为List集合,它与Collection接口中的toArray一起,构成了数组API和集合API之间的桥梁。
/* 集合变数组。 Collection接口中的toArray方法。 */ import java.util.*; class CollectionToArray { public static void main(String[] args) { ArrayList<String >al = new ArrayList<String>(); al.add("abc1"); al.add("abc2"); al.add("abc3"); /* 1.指定类型的数组到底要定义多长? 当指定类型的数组长度小于了集合的size,那么该方法内部会创建一个新的数组,数组的长度为集合的size 当指定类型的数组长度大于了集合的size,就不会新创建数组,而是用传递进来的数组。 所以创建一个刚刚好的数组最优。 2.为什么要将集合变数组? 为了限定对元素的操作。(如返回数据时,将数据变成数组) */ String [] arr = al.toArray(new String[0]); System.out.println(Arrays.toString(arr)); } }
class ArraysDemo { public static void main(String[] args) { // int[] arr =new int[]{2,5,7}; // System.out.println(Arrays.toString(arr)); String [] arr ={"abc","cc","kkk"}; //把数组编程List集合有什么好处? /* 可以使用集合的思想和方法来操作数组中的元素。(如判断是否包含:如果是数组,需要进行循环判断))。否则需要自己封装多种方法。 注意:将数组变成集合,不可以使用集合的增删方法(add,remove),因为数组的长度是固定的。 如果增删了,那么会发生UnsupportedOperationException */ List<String> list = Arrays.asList(arr); //list.add(0,"k");//UnsupportedOperationException System.out.println(list); int [] nums ={2,5,9}; List<int[]> li = Arrays.asList(nums); /* 如果数组中的元素都是对象,那么变成集合时,数组中的元素就直接转成集合中的元素。 如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存储。 */ sop(li); Integer [] nums1 ={2,5,9}; List<Integer> lis = Arrays.asList(nums1); sop(lis); } public static void sop(Object obj) { System.out.println(obj); } }
————————————————————————————————————————————
------- android培训、java培训、期待与您交流! ----------