@w460461339
2016-11-15T23:04:36.000000Z
字数 6529
阅读 1023
Java基础
嘛,今天学习的是Map这一大类以及Collections类(Collection的工具类)。(妈蛋,好不想写学习文档= -)另外还有一些例子,我们就先从Map开始吧。
Map是和Collection并列的顶层接口。这里之所以用并列,是想说明,其实Map和Collection之间并没有什么关系。只是Collection下Set子接口以及其子类中有一些功能方法是通过Map的方法实现的。
Map是双列集合,< K V >一一对应。其下有两个实现类,分别是HashMap以及TreeMap两者最大的区别就是,TreeMap可以对KeySet进行排序。
就以下几个功能,具体自己去尝试好了= -
A:添加功能:
V put(K key,V value):添加元素。
如果键是第一次存储,就直接存储元素,返回null
如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值
B:删除功能
void clear():移除所有的键值对元素
V remove(Object key):根据键删除键值对元素,并把值返回
C:判断功能
boolean containsKey(Object key):判断集合是否包含指定的键
boolean containsValue(Object value):判断集合是否包含指定的值
boolean isEmpty():判断集合是否为空
D:获取功能
Set<Map.Entry<K,V>> entrySet():返回对象对的集合
V get(Object key):根据键获取值
Set<K> keySet():获取集合中所有键的集合
Collection<V> values():获取集合中所有值的集合
E:长度功能
int size():返回集合中的键值对的对数
同样,我们用增强for进行遍历,但是由于它是对象对,我们有两种方法可以遍历:
Way1:运用keySet以及get()进行遍历。即先拿到key的集合,在遍历key的集合,去拿到对应的value。
// 创建集合对象Map<String, String> map = new HashMap<String, String>();map.put("邓超", "孙俪");map.put("黄晓明", "杨颖");map.put("周杰伦", "蔡依林");map.put("刘恺威", "杨幂");Set<String> mapSet = map.keySet();//拿到由key组成的集合for(String key:mapSet){String value=map.get(key);//拿到每个key对应的valueSystem.out.println(value);}
Way2:利用entrySet以及Entry类的getKey以及getValue方法。即先拿到元素对的集合,然后遍历集合,拿到每个元素对,再去去除key以及value。
Map<String, String> map = new HashMap<String, String>();map.put("邓超", "孙俪");map.put("黄晓明", "杨颖");map.put("周杰伦", "蔡依林");map.put("刘恺威", "杨幂");Set<Map.Entry<String,String>> mapSet=map.entrySet();for(Map.Entry<String,String> key:mapSet){String name1=key.getKey();String name2=key.getValue();System.out.println(name1+"----"+name2);}
注意,Map的实现类中,是用Set将Key储存的,所以才能保证Key的唯一性。因此,我们也知道,要让自定义类也能够体现唯一性,需要在自定义类中实行hashCode以及euqals方法。
import java.util.HashMap;import java.util.Set;class Student{//缺少hashCode以及equals方法private String name;private int age;public Student() {super();// TODO Auto-generated constructor stub}public Student(String name, int age) {super();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 class MyTreeSet {public static void main(String[] args) {HashMap<Student, String> tm= new HashMap<Student, String>();Student s1=new Student("a",1);Student s2=new Student("b",2);Student s3=new Student("c",3);Student s4=new Student("c",3);tm.put(s1, "first");tm.put(s2, "second");tm.put(s3, "third");tm.put(s4, "third");//这样的话,下面的遍历输出的是4个元素,并不会把s4与s3看做是同一个元素Set<Student> tmSet=tm.keySet();for(Student key:tmSet){String value=tm.get(key);System.out.println(value);}}}
所以,在自定义类中右击,源代码,生成hashCode以及equals方法即可(这里就贴一下这重写后的这两个方法了)
@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + age;result = prime * result + ((name == null) ? 0 : name.hashCode());return result;}@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj == null)return false;if (getClass() != obj.getClass())return false;Student other = (Student) obj;if (age != other.age)return false;if (name == null) {if (other.name != null)return false;} else if (!name.equals(other.name))return false;return true;}
要令自定义类在TreeMap中同样能够实现TreeMap的特性,除了在自定义类中加上hashCode以及equals方法以外,还需要针对TreeSort的排序功能做一些调整。
TreeSet在Map的基础之上增加了对keySet进行排序的功能。那么和TreeSet一样,需要自定义类去实现(implements)Comparable接口;或者在创建TreeMap对象的时候,传递一个Comparator对象给它的构造器。下面仅演示直接传递Comparator的方法。
TreeMap<Student, String> tm =new TreeMap<Student, String>(new Comparator<Student>() {//表示创建了一个匿名类,实现了Comparator接口,并且明确对象类型是Student//之后在该匿名类中实现了接口中的方法@Overridepublic int compare(Student s1, Student s2) {// 主要条件int num = s1.getAge() - s2.getAge();// 次要条件int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;return num2;}});
两个案例,一个是统计字符串中每个字符出现的次数;另一个是集合嵌套遍历。嵌套遍历比较简单的,除了之前说的,自定义类放在key的位置上,需要重写一些方法,实现一些接口,其他弄清楚每一层关系就好。下面来写一下统计每个字符串出现的次数的程序。
需求分析:
A 键盘录入一串字符串
B 将字符串转化为字符数组
C 将每个字符存入TreeSet。先用contains判断,是否为null
为null,key为该字符,value写1
不为null,key为该字符,value在原基础上+1
D 显示
import java.util.Scanner;import java.util.Set;import java.util.TreeMap;public class myString {public static void main(String[] args) {//录入字符串,并把它们转成字符数组Scanner in = new Scanner(System.in);String str=in.nextLine();char[] chStr=str.toCharArray();//创建TreeMap对象,注意key和value类型TreeMap<Character, Integer> chTm=new TreeMap<Character, Integer>();//遍历字符数组(居然没有用增强for,自己脑抽了),把元素放入TreeMapfor(int i=0;i<chStr.length;i++){Integer value=chTm.get(chStr[i]);if(value==null){chTm.put(chStr[i], 1);}else{chTm.put(chStr[i], value+1);}}//遍历TreeMap,输出Set<Character> tmSet=chTm.keySet();for(Character key:tmSet){Integer value =chTm.get(key);System.out.println(key+"("+value+")");}}}
注意啊!这货是Collections类,比Collection接口多一个s的!而且人家是货真价实的类,不是接口啊!虽然Collections类中全部是静态方法,直接用类名调用方法就好,不用创建对象,但还是要明确,这货是个类!
主要有这么几个方法比较重要:
A:public static <T> void sort(List<T> list) 排序
B:public static <T> int binarySearch(List<?> list,T key) 二分查找
C:public static <T> T max(Collection<?> coll)最大值
D:public static void reverse(List<?> list)反转
E:public static void shuffle(List<?> list)乱序
注意,除了找最大值以外,其他都只对List下的类开放,Set什么的退散。另外,二分查找是在序列排序之后才有用的,所以记得先对序列进行排序之后在二分查找。
测试什么的,这里就不写了,自己慢慢试试就好。
需求:
54张牌,随机发给三个人,并留下三张牌,最后按照一定顺序查看
思路:
A:按照一定的顺序将54张牌存储在HashMap中,每张牌的面值对应一个编号,从0到53
B:将这54个编号单独存储在ArrayList中,利用shuffle打乱,并用下标作为索引分发
C:每个人以及底牌用TreeSet进行储存,实现自然排序
D:遍历,展示
import java.util.ArrayList;import java.util.Collections;import java.util.HashMap;import java.util.TreeSet;public class myDoudizhu {public static void main(String[] args) {//创建花色String[] color={"♥","♠","♣","◇"};//创建牌号String[] number={"3","4","5","6","7","8","9","10","J","Q","K","A","2",};//创建计数器以及牌盒Integer cnt=0;HashMap<Integer, String> hm=new HashMap<Integer, String>();//创建记录编号的ArrayListArrayList<Integer> array=new ArrayList<Integer>();//往牌盒中放牌,并网array中塞入编号for(String nuKey:number){for(String coKey:color){hm.put(cnt, coKey.concat(nuKey));array.add(cnt);cnt++;}}hm.put(cnt,"小王");array.add(cnt);cnt++;hm.put(cnt,"大王");array.add(cnt);//洗牌Collections.shuffle(array);//创建打牌的人TreeSet<Integer> player1=new TreeSet<Integer>();TreeSet<Integer> player2=new TreeSet<Integer>();TreeSet<Integer> player3=new TreeSet<Integer>();TreeSet<Integer> dipai=new TreeSet<Integer>();//发牌;此处注意,只是把每张牌在HahsMap中编号(Key)发了//按照每轮每人一张,最后3张留作底牌的顺序发牌for(int i=0;i<array.size();i++){Integer key=array.get(i);if(i>=array.size()-3){dipai.add(key);}else if(i%3==0){player1.add(key);}else if(i%3==1){player2.add(key);}else if(i%3==2){player3.add(key);}}//每个人都得到了13个编号,底牌得到3个编号,并且由TreeSet自然排序好//靠这个顺序,以及按照HashMap中我们定义顺序去除牌,并显示//完成最终的斗地主顺序的现实牌showCard("player1",player1,hm);showCard("player2",player2,hm);showCard("player3",player3,hm);showCard("底牌",dipai,hm);}public static void showCard(String name,TreeSet<Integer> card,HashMap<Integer, String> hm){System.out.print(name);for(Integer key:card){String value=hm.get(key);System.out.print("\t"+value);}System.out.println();}}