@w460461339
2016-11-16T07:04:36.000000Z
字数 6529
阅读 826
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对应的value
System.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方法即可(这里就贴一下这重写后的这两个方法了)
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public 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
//之后在该匿名类中实现了接口中的方法
@Override
public 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,自己脑抽了),把元素放入TreeMap
for(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>();
//创建记录编号的ArrayList
ArrayList<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();
}
}