传智博客---集合之Map接口

package com.zhou.jihe;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;

public class TestMap {

/**
* Map接口:
*     1.Map和Collection、Iterator并列的顶级接口,并且Map是用来产生集合的,即用Map来定义Collection;
*     2.Map接口的实现类有:HashMap,Hashtable,LinkedHashMap,TreeMap,Properties;
*     3.Map接口用于保存具有映射关系的数据,因此Map集合里保存着两组值,一组值用于保存Map里的Key,另一组用于保存Map里的value;
*     4.Map中的key和value都可以是任何引用类型的数据;
*     5.Map中的key不允许重复,即同一个Map对象的任何两个key通过equals()方法返回false;
*     6.key和value之间存在着单向一对一的关系,即通过指定的key总能找到唯一的,确定的value,但是反过来,用value找不到key;
*/
public static void main(String[] args) throws FileNotFoundException, IOException {
/**
* 一、 Map最典型的实现是HashMap实现类:
*      HashMap和HashSet有什么关系(在eclipse中用ctrl+shift+t查找HashSet),可以看出HashSet是用HashMap来进行定义的,我们在创建HashSet的时候实际上它是把这个Map给初始化了,于是我们在进行遍历的时候都是调用的是Map的方法,具体用的是HashMap里面的那个key,那个值就是Object里面的常量值;所以说HashMap和HashSet是一脉相承;
*      HashMap定义了HashSet:HashMap里面的键为HashSet里面的元素;
*/
//1.创建一个Map的HashMap实现类对象;
Map map = new HashMap();
//Map<String,Object> map = new HashMap<>();//泛型的方式
//2.Map接口中有一些方法,下面将这些方法作一些归类;
 //2.1  向Map中添加元素的方法,关于添加的方法有两个:put(key,value),put(map);
    map.put("AA", new Person("AA", 12));//放入一个指定的键值对;
    map.put("AA", new Person("AAA", 12));//这样的话其键相同,equals()返回true,第二个会把第一个覆盖掉;
    map.put("BB", new Person("BB", 15));
    map.put("CC", new Person("CC", 16));
    map.put("DD", new Person("AAA", 12));
 //2.2  从Map中取出元素的方法(遍历),map是由键和值组成的,所以我可以得到键的集合和值的集合;
    //2.2.1  得到键的集合;
       Set keyset = map.keySet();//用map的keySet()方法来得到键的集合,这里用到了Set接口;
       //我通过遍历键的方式来找到值;
         for(Object key:keyset){
 Object value = map.get(key);//通过map的get(key)方法得到value;
 System.out.println(key+":"+value);//打印出一个键值对的集合;
         }
         System.out.println("-----------------------------------------");
   //2.2.2  直接得到value的集合;
        Collection values = map.values();
        System.out.println(values.getClass());//看看values是什么,HashMap$Values,values就是HashMap的内部类,它返回的就是values;
        //遍历value集合,需要说明是,value可以重复;
        for(Object val:values){
System.out.println(val);
        }
        System.out.println("-----------------------------------------");
//    //2.2.3 得到键值对的集合,要求是要使用泛型,不用泛型是不行的;
//         for(Map.Entry<String,Object> entry:map.entrySet()){
// String key = entry.getKey();
// Object value = entry.getValue();
// System.out.println(key+":"+value);
//         }
//
 //2.3  移除元素的方法;
//        map.remove("AA");//移除指定的键;
 //2.4 工具方法:
        //2.4.1  size()方法;
     System.out.println(map.size());//移除了之后就4变成3
     System.out.println("-----------------------------------------");
     System.out.println(map);// 因为Map重写了toString()方法,所以打印时就能看得到:{AA=Person [name=AAA, age=12]}
        //2.4.2 contains(),isEmpty()
     System.out.println(map.containsKey("BB"));//true
     System.out.println(map.containsValue(new Person("CC", 16)));//true
     System.out.println(map.isEmpty());//false
/**
* 二、HashMap和Hashtable:
*     HashMap和Hashtable是Map接口的两个典型的实现类;
*        区别:
*           Hashtable是一个古老的实现类,不建议使用;
*           Hashtable是一个线程安全的Map实现,但HashMap是线程不安全的;
*           Hashtable不允许使用null作为key和value,而HashMap则可以;
*     与HashSet集合不能保证元素的顺序一样,Hashtable、HashMap也不能保证其中key-value对的顺序,实际上是不能保证那个键的顺序,当然值的顺序也不能保证;
*     Hashtable、HashMap判断两个key相等的标准是:两个key通过equals()方法返回true,hashCode值也相等;
*     Hashtable、HashMap判断两个value相等的标准是:两个value通过equals()方法返回true;
*          
*/
/**
 * 三、LinkedHashMap:
 *       LinkedHashMap是HashMap的子类;
 *       LinkedHashMap可以维护Map的迭代顺序:迭代顺序与key-value的插入顺序一致;
 *       LinkedHashSet实际上也是LinkedHashMap来进行定义的,所以所以说LinkedHashMap可以维护Map的迭代顺序;
 */
 /**
  * 四、TreeMap:(TreeSet是由TreeMap来进行定义的,TreeSet的所有思想在TreeMap里同样适用,只不过TreeSet针对的是所有元素,而TreeMap针对的是所有的key)
  *      TreeMap存储key-value对时,需要根据key对key-value对进行排序,TreeMap可以保证所有的key-value对处于有序状态;
  *      TreeMap的key的排序:(跟TreeSet里面对那个Set元素的排序方式一样,对比TreeSet进行使用)
  *               自然排序:TreeMap的所有的key必须实现Comparable接口,而且所有的key应该是同一个类的对象,否则将会抛出ClassCastExcertion类型转换异常;
  *               定制排序:创建TreeMap时,传入一个Comparator接口对象,该对象负责对TreeMap中所有的key进行排序,此时不需要Map的key实现Comparable接口;
  *
  */
     Comparator comparator = new Comparator() {//匿名内部类
@Override
public int compare(Object o1, Object o2) {
//这里来比较两个Person对象的age,按年龄排序;
if(o1 instanceof Person && o2 instanceof Person ){
Person p1 = (Person) o1;
Person p2 = (Person) o2;
//return p1.getAge() - p2.getAge();//年龄的升序排列
return -(p1.getAge() - p2.getAge());//按年龄降序排列
}else{
throw new ClassCastException("不能转换为Person类型");
}
}
};
     //创建一个TreeMap对象;
     TreeMap tm = new TreeMap(comparator);//定制排序:在创建 TreeMap是传入一个Comparator实现类对象进来,如果不传的话它就会把这个键试着转换成Comparable,发生类型转换异常;
     //放入一些元素到集合中,这时候我们的键需要是Person对象;
     tm.put(new Person("AAA", 12), "AAA");
     tm.put(new Person("BBB", 13), "BBB");
     tm.put(new Person("CCC", 11), "CCC");
     tm.put(new Person("DDD", 9), "DDD");
     //遍历上面的元素;
     keyset = tm.keySet();//得到一个键的集合
     for(Object key:keyset){
 Object value = tm.get(key);//通过key得到value;
 System.out.println(key+":"+value);
     }
     /**
      * 五、Properties实现类:
      *       Properties类是Hashtable的子类,该对象用于处理属性文件;
      *       由于属性文件里的value。key都是字符串类型,所以Properties里的value和key都是字符串类型的;
      *       Properties文件在java中对应的是一个Properties类的对象;
      */
     //加载我们创建的那个Properties文件的步骤:在JDBC时为了不把数据库的信息写死,一般就把数据库的信息放在这样的属性文件中,处理属性文件的步骤基本就是下面这样的;
       //1.创建一个Properties类的对象;
          Properties  properties = new Properties();
       //2.使用IO六加载对应的Properties文件;
          properties.load(new FileInputStream("jdbc.properties"));// 需要传入一个FileInputStreamIO流对象,其构造方法是有参数的,参数就是那个属性文件名的全称;
       //3.得到对应的属性值,通常情况下这个键是已知的,通过这个键去得到属性值,当然也可以用Map里面的方法同时获取键和值,但是开发的时候都是知道了键,直接去获取值;
          String url = properties.getProperty("url");//得到一个url键对应的值
                  System.out.println(url);
}

}


package com.zhou.jihe;
public class Person {
//当我重写equals方法集合的移除也会失败
//   @Override
// public boolean equals(Object obj) {
// // TODO Auto-generated method stub
//// return super.equals(obj);
// return false;
// }
//用IDE直接生成hashCode()和equals()方法
//hashCode()方法决定着我们放的这个元素在集合中的位置,如果两个元素比较equals()方法返回fasle的话,那么hashCode()方法返回值应该也不相等,应该放在两个位置;
//反过来,如果equals()方法返回的true的话,那么hashCode()返回值应该也相等,它们是同一个元素,应该放在同一个地方;
/**
* 正常情况下我们这么来做:两个对象的equals()方法返回true,hashCode()方法返回值必相等;
* 通常情况下,我们使用eclipseIDE帮我们生成hashCode()和equals()方法就可以;
* 学习的时候我们可以这样来试一下,不建议开发的时候这样来做,如果equals()方法返回true,它两是同一个元素,但是hashCode()值不一样,那么这两个对象都可以放到这个集合里面去,这个是矛盾的事
*/
/**
* hashCode()方法的要求:
*    HashSet集合判断两个元素相等的标准:两个对象通过equals()方法方法比较返回true相等,并且两个对象的hashCode()方法返回值也相等。
*    如果两个对象通过equals()方法返回true,这两个对象的hashCode值也应该相同;
*
* 重写hashCode()方法的基本原则:
*    1.在程序运行时,同一个对象多次调用hashCode()方法应该返回相同的值;
*    2.当两个对象的equals()方法比较返回true时,这两个对象的hashCode()方法的返回值也应该相等;
*    3.对象中用作equals()方法比较的(Field)区域,都应该用来计算hashCode值;  
*      
*/
// private static int init = 0;
@Override
public int hashCode() { //这个hashCode值和age的值联合到一起来返回的一个结果
final int prime = 31; //用这个素数是为了防止name的hashCode值和age的值不一样,但是有可能age和name的hashCode值相加得到的那个数可能一样的情况;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
//      return init++;//不允许
}
//这个是一个一个属性比的,这个是IDE自动帮我们生成的equals()方法,这个是可信赖的;
@Override
public boolean equals(Object obj) {
if (this == obj) //如果这两个对象是一个的话,返回true
return true;
if (obj == null) //如果传的这个对象是空的话,返回fasle
return false;
if (getClass() != obj.getClass()) //如果类型不一致的话,返回false
return false;
Person other = (Person) obj; //否则,强转
if (age != other.age) //如果年龄不一样的话,返回false
return false;
if (name == null) { //如果名字为空
if (other.name != null) //另外一个的名字不为空返回fasle
return false;
} else if (!name.equals(other.name)) //如果名字不一样的话,返回fasle
return false;
return true; //否则,最后返回true,表示一样;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() {
super();
}
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;
}
private String name;
private int age;
}


本文出自 “IT技术JAVA” 博客,转载请与作者联系!

你可能感兴趣的:(map)