集合框架3(Map集合,Collections,Arrays工具类)
Map集合:
特点:该集合存储键值对,一对一对的往里存储,而且要保证键的唯一性。将键映射到值得对象,一个映射不能包含重复的键,每个键最多只能映射到一个值。
<1>添加:
put(K key,V value);将指定的值与此映射中指定的键关联。
putAll(Map<? extends K,? extends V> m);从指定的映射中将所有的映射关系复制到此映射中。
<2>删除:
clear( );从此映射中移除所有映射关系。
remove(Object key);如果存在一个键的映射关系,则将其从此映射中移除。
<3>判断:
containsValue(Object value);如果此映射将一个或多个键映射到指定值,则返回true。
containsKey(Object key);如果此映射包含指定键的映射关系,则返回true。
isEmpty( );如果此映射关系未包含键值映射关系,则返回true。
<4>获取:
get(Object key);返回指定键所映射的值,如果此映射不包含该键的映射关系,则返回null。
size( );返回此映射关系中的关系数。
values( );返回此映射中包含的值的 Collection
视图。
Hashtable:
特点:底层是哈希表数据结构,不可以存入空键空值,线程同步。
如果将不同的值传递给相同的键,那么后添加的值会覆盖掉原来的值,put方法将返回被覆盖的值。
如何获取到Map集合中的键值对映射关系呢?
<1>Keyset:将Map中所有的键存入Set集合中,因为Set具备迭代器,可以迭代取出所有的键,再根据get方法,获取到每一个键对应的值。
1: class MapDemo
2: {
3: public static void main(String[] args)
4: {
5: Map<String,String> map=new HashMap<String,String>();
6:
7: //添加元素
8: map.put("01","zhangsan1");
9: map.put("02","zhangsan2");
10: map.put("03","zhangsan3");
11:
12: //先获取Map集合的所有键的Set集合
13: Set<String> keySet=map.keySet();
14:
15: //有了Set集合,获取其迭代器
16: Iterator<String> it=keySet.iterator();
17: while(it.hasNext())
18: {
19: String key=it.next();
20:
21: //有了键值,通过Map的get方法来获取相对应的值
22: String value=map.get(key);
23: System.out.println(key+value);
24: }
25: }
26: }
27:
<2>entrySet:
返回该映射中包含的映射关系的Set视图
1:
2:
3: class MapDemo
4: {
5: public static void main(String[] args)
6: {
7: Map<String,String> map=new HashMap<String,String>();
8:
9: //添加元素
10: map.put("01","zhangsan1");
11: map.put("02","zhangsan2");
12: map.put("03","zhangsan3");
13:
14: //将Map集合中的映射关系取出,存入到set集合中
15: Set<Map.Entry<String,String>> entrySet=map.entrySet();
16: Iterator<Map.Entry<String,String>> it=entrySet.iterator();
17: while(it.hasNext())
18: {
19: Map.Entry<String,String> me=it.next();
20: String key=me.getKey();
21: String value=me.getValue();
22: System.out.println(key+value);
23: }
24: }
25: }
26:
HashMap:
特点:底层是哈希表数据结构,允许使用空键空值,该集合是非同步的。
练习,在Map中存储学生和对应的地址,学生有姓名和年领两个属性。
<1>每个学生都有对应的归属地
<2>姓名和年龄相同的视为同一个学生
<3>保证学生的唯一性
1: import java.util.*;
2:
3: class Student implements Comparable<Student>
4: {
5: private String name;
6: private int age;
7:
8: Student(String name,int age)
9: {
10: this.name=name;
11: this.age=age;
12: }
13:
14: public String getName()
15: {
16: return name;
17: }
18:
19: public int getAge()
20: {
21: return age;
22: }
23:
24: //如果Student对象存储在HashSet中,HashSet通过hashCode和equals来保证元素的唯一性
25: //如果hashSet相同,则判断equals是否为true,如果为true,则说明为相同的元素
26: public int hashCode()
27: {
28: return 0;
29: }
30:
31: public boolean equals(Object obj)
32: {
33: if(!(obj instanceof Student))
34: throw new ClassCastException("类型不匹配");
35: Student s=(Student)obj;
36: return this.name.equals(s.name)&&this.age==s.age;
37: }
38:
39: //如果Student对象存储在TreeSet中,则实现Comparable接口,重写CompareTo方法来进行比较
40: public int compareTo(Student stu)
41: {
42: if(this.age>stu.age)return 1;
43: else if (this.age==stu.age)
44: {
45: return this.name.compareTo(stu.name);
46: }
47: else return -1;
48:
49:
50:
51: }
52:
53:
54:
55: }
56:
57:
58: class MapTest
59: {
60: public static void main(String[] args)
61: {
62: Map<Student,String> map=new HashMap<Student,String>();
63:
64: map.put(new Student("zhangsan1",20),"beijing");
65: map.put(new Student("zhangsan2",30),"shanghai");
66: map.put(new Student("zhangsan3",40),"beijing");
67: map.put(new Student("zhangsan4",50),"jinan");
68: map.put(new Student("zhangsan4",60),"beijing");
69: map.put(new Student("zhangsan1",20),"tianjin");
70:
71: Set<Map.Entry<Student,String>> entrySet=map.entrySet();
72:
73: Iterator<Map.Entry<Student,String>> it=entrySet.iterator();
74:
75: while(it.hasNext())
76: {
77: Map.Entry<Student,String> me=it.next();
78: Student key=me.getKey();
79: String value=me.getValue();
80:
81: System.out.println("key="+key.getName()+"..."+key.getAge()+"value="+value);
82: }
83:
84: }
85: }
86:
TreeMap:
特点:底层是二叉树数据结构,线程不同步,可以用于给Map集合中的键进行排序。
需求:对学生对象的年龄进行升序排序。
分析:因为数据是以键值对的形式存在的,所有要使用可以排序的Map集合,TreeMap。
在Student中只需要实现Comparable接口,重写compareTo方法。
练习:需求为获取字符串中字母出现的次数,sdfgzxcvasdfxcvdf,希望打印结果为:a(1)d(3)。。。。。。
1: class MapTest3
2: {
3: public static void main(String[] args)
4: {
5: String str="sdfgzxcvasdfxcvdf";
6: String s=charCount(str);
7: System.out.println(s);
8:
9: }
10:
11: public static void charCount(String str)
12: {
13: char[] chs=str.toCharArray();
14: TreeMap<Character,Integer> tm=new TreeMap<Character,Integer>();
15:
16: //对字符串挨个进行判断
17: for(int x=0;x<chs.length;x++)
18: {
19:
20: Integer value=tm.get(chs[x]);
21: //如果没有该字符,则在该集合中新建一对键值对映射关系
22: if(value==null)
23: {
24: tm.put(chs[x],1);
25: }//如果存在该字符,则将得到的value值进行加1,然后再存入原来得集合中去
26: else
27: {
28: value=value+1;
29: tm.put(chs[x],value);
30: }
31: }
32:
33: StringBuilder sb=new StringBuilder();
34: Set<Map.Entry<Character,Integer>> entrySet=tm.entrySet();
35:
36: Iterator<Map.Entry<Character,Integer>> it=entrySet.iterator();
37: while(it.hasNext())
38: {
39: Map.Entry<Character,Integer> me=it.next();
40: Character ch=me.getKey();
41: Integer value=me.getValue();
42:
43: sb.append(ch+"("+value+")");
44: }
45:
46: return sb.toString();
47: }
48: }
49:
Collections:
1:
2: //列表中的所有元素均必须实现Comparable接口,根据自然顺序来进行比较
3: public static <T extends Comparable<? super T>> void sort(List<T> list)
4:
5: //根据指定的比较器来进行排序
6: public static <T> void sort(List<T> list,Comparator<? super T> c)
7:
8: //根据自然顺序来去最大
9: public static <T extends Object &Comparable<? super T>>T max(Collection<? extends T> coll)
10:
11: //binarySearch,必须为有序集合才可以使用,二分搜索法,返回值为该元素的角标,
12: //如果想搜索的元素不在该集合中,则返回一个负数,[-(插入点)-1]
13: int index=Collections.binarySearch(list,"aaaa");
14:
15: //原理是:
16: public static int halfSearch(List<String> list,String key)
17: {
18: int max,min,mid;
19: max=List.size()-1;
20: min=0;
21: while(min<=max)
22: {
23: min=(max+min)>>1;
24: String str=list.get(mid);
25: int num=str.compareTo(key);
26: if(num>0)
27: max=mid-1;
28: else if(num<0)
29: min=mid+1;
30: else
31: return mid;
32: }
33: return -(mid)-1;
34: }
35:
36:
1:
2: //Collections.fill(list,"pp");将集合中的元素全部替换成pp
3: //自己编写函数实现将集合中的部分元素替换,包含头也包含尾
4: public static void fill2(List list,int start,int end,String str)
5: {
6: for(int x=start;x<=end;x++)
7: {
8: list.set(x,str);
9: }
10:
11: System.out.println(list);
12: }
13:
1:
2: //Collections.replaceAll(list,"aaa","pp");将集合中的所有aaa替换成pp
3: //Collections.reverse(list);将list集合中的所有元素反转
4: public static void orderDemo()
5: {
6: //将自然顺序逆转,反序打印
7: //将一个自定义的比较器作为参数传递给reverseOrder,它会将比较器定义的顺序进行逆转
8: TreeSet<String> ts=new TreeSet<String>(Collection.reverseOrder(new StrLenComparator()));
9:
10: ts.add("abcde");
11: ts.add("aaa");
12: ts.add("kkk");
13: ts.add("ccc");
14:
15: Iterator it=ts.iterator();
16: while(it.hasNext())
17: {
18: System.out.println(it.next());
19: }
20: }
21:
22: //集合是线程不安全的,多线程存在安全隐患
23: //synchronized List(list);
24: //synchronized Set(set);
Arrays工具类:
asList:将数组转换成list集合
将数组转换成集合的好处:
可以使用集合的思想和方法来操作数组中的元素
1:
2: String[] arr={"abc","cc","kkkk"};
3: List<String> list=Arrays.asList(arr);
4: //如果希望判断数组中是否有"cc"元素,必须遍历整个数组的所有元素,
5: //将数组转换成集合以后,可以使用contains方法来进行判断
6: System.out.println("contains:"+list.contains("cc"));
7: System.out.println(list);
8: //注意:如果将数组变成集合,不可以使用集合的增删方法,因为数组的长度是固定的。
9: //如果数组中的元素都是对象,那么变成集合时,数组中的元素就直接变成集合中的元素
10: //例如:Integer[] nums={2.3,4};
11: // List<Integer> li=Arrays.asList(nums);
12: //如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在
13: //例如:int[] nums={2,3,4};
14: // List<int[]> li=Arrays.asList(nums);
15:
将集合转变成数组:利用Collection接口中的toArray方法
1: public static void main(String[] args)
2: {
3: ArrayList<String> al=new ArrayList<String>();
4: al.add("abc1");
5: al.add("abc2");
6: al.add("abc3");
7:
8: String[] arr=al.toArray(new String[0]);
9: System.out.println(Arrays.toString(arr));
10:
11: }
12: //打印结果为:[abc1,abc2,abc3]
13: //指定类型的数组应该定义成多长呢?
14: //当指定类型的数组长度为小于集合的size,那么该方法内部会创建一个新的数组,长度为size
15: //String[] arr=al.toArray(new String[5]);
16: //打印结果为[abc1,abc2,abc3,null,null]
17: //当指定类型的数组长度大于集合的size,就不会创建一个新的数组,而是使用传递进来的数组,
18: //所以创建一个刚好的数组最优
19:
为什么要将集合转换成数组呢?
为了限定对元素的操作,例如不想对集合进行增删,就将它变成数组即可。