JAVA的Map接口及实现类,properties类的配置文件、collections工具类的常用方法

Map接口及实现类

Map接口

元素存储方式:

  • Collection接口中的元素是单个存在的
  • Map接口中的元素但是成对存储的,我们将这种存储数据的数据对,称之为键值对(key-value)

TreepMap和HashMap的用法是一模一样的,但是它是Tree,所以在进行比较的时候和上一篇文章的Set接口及实现类中有一个TreeSet的比较值得方法是一模一样的。

  • 自然排序:都是通过实现Comparable接口,重写compareTo方法
  • 定制排序:排序器类实现Comparetor接口,重写其中的compare方法

在这里就不做过多的冗余的介绍了。
那么我们就以HashMap为标准,学习Map接口的使用方式。

HashMap

上一篇文章讲了List和Map两个接口及实现类,今天要说的Map接口的实现类和前两个还是不一样的,Map集合使用的方法先看代码,代码如下:

public class TestHashMap {

    public static void main(String[] args) {

        //[1]创建Map接口实习类对象的构造方法
        HashMap<String, Person> map1 = new HashMap<String, Person>();

        //[2]增
        map1.put("张三", new Person("张三", 22, "111111"));  //向当前Map中单独添加键值对
        map1.put("李四", new Person("李四", 23, "222222"));
        map1.put("王五", new Person("王五", 20, "333333"));
        map1.put("陈六", new Person("陈六", 21, "444444"));
        map1.put("田七", new Person("田七", 24, "555555"));
        
        HashMap<String, Person> map2 = new HashMap<String, Person>();
        map2.putAll(map1);  //将map1中所有的键值对批量添加到map2当中去
        
        //测试Map中,键和值得重复性问题
        
        //[1.1]测试:键重复,值不重复
        Person p8 = new Person("王八", 26, "666666");
        map1.put("张三", p8);  //在Map中,键不能重复存储,如果键重复了,put方法将会变成修改方法
        
        //[1.2]测试:键不重复,值重复
        map1.put("白九", p8);  //在Map集合中,同一个值是允许重复出现的
       
        //[1.3]测试:键和值都重复
        map1.put("白九", p8);  //如果将一个重复的键值对存入Map中,键值对不会重复存储

        /*
         * 综上所述:
         * 1.Map中的键是不能重复的(Set)
         * 2.Map中的值是可以重复的(Collection)
         */
        
        Person p3 = new Person("张三", 22, "111111");
        map1.put("张三", p3);
        map1.put("小张", p3);
        
        //[3]删
        Person rmv = map1.remove("白九");  //根据传入的key删除Map中的键值对,并肩这个键值对中的值进行返回
        System.out.println("Remove by key: " + rmv);
        
        boolean remove = map1.remove("张三", p8);  //通过制定一组key和value删除Map中的一个键值对
        System.out.println("Romove by key and value: " + remove);
        
//      map1.clear();  //清空整个Map
        
        //[4]改
        /*
         * Map集合中并没有提供独立的修改方法
         * 在Map集合当中传递一个重复键的新值,
         * 这个新的值将会替代这个键对应的原有的值
         */

        Person rp = map1.replace("小张", p8);  //按照指定的key将当前Map中的对应的value进行替换,被覆盖的值作为方法的返回值返回
        System.out.println("Replace by key: " + rp);

        boolean replace = map1.replace("张三", p8, p3);  //只有在指定的key能够和oldValue对应的前提下,才能够将oldValue替换为newValue
        System.out.println("Replace by key and value: " + replace);

        /*
         * [5]查:
         * ①获取所有键构成的keySet,通过遍历keySet获取每个值,实现键值对遍历
         * ②通过values()方法,直接获取所有value组成的Collection接口实现类对象,通过遍历这个集合实现对值的遍历
         */
        System.out.println(map1);

        //注意:在Map中因为值可能不是唯一的,所以不能通过值找到键
        Person tmp = map1.get("小张");  //get方法是通过指定一个键,获取当前Map中与这个键对应的value值
        System.out.println("Get by key: " + tmp);

        //获取Map中所有键构成的集合——一个Set<K>的集合(本例中是Set<String>)
        Set<String> keys = map1.keySet();
        String tmpKey = "";
        Person tmpValue = null;
        Iterator<String> ite = keys.iterator();
        while(ite.hasNext()) {

            //[1]首先获取key的Set结合中的一个key(String)
            tmpKey = ite.next();  //此时返回的是键的Set集合中,当前的一个key(String)

            //[2]通过Map的get方法和上面获取的key来找到与之对应的value(Person)
            tmpValue = map1.get(tmpKey);

            //[3]打印分别获取的键和值
            System.out.println("[key=" + tmpKey + ", value=" + tmpValue + "]");

        }

        System.out.println("----------");

        //通过values()方法返回一个存储Map中所有值的一个Collection结合实现类对象,存储元素泛型为V(本例中V=Person)
        Collection<Person> valueCollection = map1.values();
        Iterator<Person> ite2 = valueCollection.iterator();  //获取包含所有值的迭代器对象
        while(ite2.hasNext()) {
            System.out.println("value=" + ite2.next());
        }

        System.out.println("----------");

        //[6]其他方法
        System.out.println("Size: " + map1.size());  //返回当前map中,键值对的对数

        System.out.println("Is empty: " + map1.isEmpty());  //判断当前Map中是否不存在键值对

        System.out.println("Contains key: " + map1.containsKey("李四"));  //判断当前Map中是否包含指定的key

        System.out.println("Contains value: " + map1.containsValue(p8));  //判断当前Map中是否包含指定的value

    }
}

HashMap的内部实现原理

HashMap中对键值对的存储方式:
在这里插入图片描述

  1. 在Map当中,键和值不是分开存储的,反而一个键和对应的值是保存在同一个结构当中的
    我们将这种能够保存一个键 + 对应值的结构称之为Entry(键值对):Entry = key + value
  2. Entry本身是一个定义在Map接口中的内部接口,在HashMap中,Entry接口的实现类是Node,Node类是HashMap的内部类
  3. 通过HashMap的对象来获取所有的键值对(Entry)对象:
public class TestHashMap2 {

    public static void main(String[] args) {

        HashMap<String, Person> map = new HashMap<String, Person>();
        map.put("张三", new Person("张三", 22, "111111"));
        map.put("李四", new Person("李四", 23, "222222"));
        map.put("王五", new Person("王五", 20, "333333"));
        map.put("陈六", new Person("陈六", 21, "444444"));
        map.put("田七", new Person("田七", 24, "555555"));

        /*
         * Entry和Entry之间:
         * 1.是无序的,就是因为Entry的无序排列,才导致Map中键值对的无序性
         * 2.不可能重复:虽然键值对之间的值有可能重复,但是键是不可能重复的,所以两个键值对之间不可能重复,也就是Entry之间不存在重复元素
         * 综上所述:同一个Map中的Entry是无序不重复的
         * 所以:可以使用Set集合保存Map中的所有Entry对象
         */
         
        /*
         * Set集合:有上述讨论得知,所有的键值对对象应该保存在一个Set集合中
         * 
         * Set<Entry>:每一个键值对对象就是一个Entry对象,将一个Map中所有的键值对都封装为Entry之后
         * 将这些Entry放在Set集合中,所以Set集合的泛型类型为Entry类型
         * 
         * Set<Entry<String, Person>>:每一个Entry对象中,都保存着一对key和value
         * 为了指定这个key和value的类型,所以Entry也具有泛型
         * Entry的泛型应该匹配HashMap的泛型类型定义
         * 
         * Map通过方法entrySet()返回当前Map中所有键值对对象的Set集合
         */
        Set<Entry<String, Person>> entries =  map.entrySet();

        /*
         * Iterator ite是从Map中得到所有键值对对象集合的Set中抽取的迭代器
         * 所以当前迭代器中保存的对象类型一定和Set中元素类型保持一致
         * 所以是Entry<String, Person>
         */
        Iterator<Entry<String, Person>> ite = entries.iterator();

        Entry<String, Person> entry = null;  //临时变量
        while(ite.hasNext()) {
            entry = ite.next();
            System.out.println("Entry [key=" + entry.getKey() + ", value=" + entry.getValue() + "]");
        }
    }
}

注意:HashSet的内部实现就是HashMap,每一个添加进入HashSet中的元素,都相当于内部HashMap的键,内部HashMap的值是一个Object类型的常量,这就巧妙的利用HashMap实现HashSet中元素无序不重复的需求。

Map接口的其他实现类

public class TestMap {

    public static void main(String[] args) {

        String name1 = "张三";  //强引用的String对象
        Person p1 = new Person("张三", 22, "111111");  //强引用的Person对象

        String name2 = "李四";
        Person p2 = new Person("李四", 23, "222222");

        ///[0]设置HashMap的对照组
        HashMap<String, Person> map = new HashMap<String, Person>();

        map.put(name1, p1);
        map.put(new String("张三"), p1);

        /*
         * 对象的强弱引用:
         * 对象的强引用:如果一个对象本体,具有保存其内存地址的变量在引用它,我们认为这个对象本体是强引用对象
         * 对象的弱引用:如果一个对象本体在内存中的地址,没有保存在任何引用变量中,我们成这样的对象为弱引用对象
         */
        map.put(new String("王五"), new Person("王五", 26, "333333"));

        /*
         * HashMap中,认为键相同的条件是,两个键对象的内容相同
         * 也就是equals方法返回true
         * 我们就认为两个键是相同的
         */
//      System.out.println(map)

        //[1]IdentityHashMap
        /*
         * 强Hash表:
         * 强在对“键相同”这个条件的判别上:
         * 在IdentityHashMap中,只有两个键严格复合==比较返回true
         * 我们才认为两个键是重复
         * 如果两个键的内容相同,但是所在的内存地址不同,
         * 在IdentityHashMap中,也算作是两个不同的键
         */
        IdentityHashMap<String, Person> iMap = new IdentityHashMap<String, Person>();

        iMap.put(name1, p1);
        iMap.put(name2, p2);
        
        iMap.put(new String("张三"), p1);

        System.out.println(iMap);

        //[2]WeakHashMap
        /*
         * 弱Hash表:
         * 弱在对键的引用上
         * 在一般的HashMap中,如果键值对的键是弱引用对象,及时运行垃圾回收机制,这个键值对也不会被回收
         * 但是在WeakHashMap当中,如果一个键值对的键是一个弱引用对象
         * 那么如果垃圾回收机制运行,这个以弱引用为键的键值对将会被从Map中删除
         */
        WeakHashMap<String, Person> wMap = new WeakHashMap<String, Person>();

        wMap.put(name1, p1);
        wMap.put(name2, p2);

        wMap.put(new String("王五"), new Person("王五", 26, "333333"));

        //通过下列代码手动执行JVM的垃圾回收机制
        System.gc();
        System.runFinalization();

        System.out.println("----------");

        System.out.println(map);
        System.out.println(wMap);
    }
}

TreeMap

properties

Properties类继承自Hashtable类并且实现了Map接口,也是使用一种键值对的形式来保存属性集。不过Properties有特殊的地方,就是它的键和值都是字符串类型。
所以大多数是用它来做为配置文件来进行使用的

properties的常用方法

  1. load(InputStream inStream)
  2. store(OutputStream out, String comments)
  3. getProperty/setProperty

load(InputStream inStream)

这个方法可以从.properties属性文件对应的文件输入流中,加载属性列表到Properties类对象。如下面的代码:

Properties pro = new Properties();
FileInputStream in = new FileInputStream("a.properties");
pro.load(in);
in.close();

store(OutputStream out, String comments)

这个方法将Properties类对象的属性列表保存到输出流中。如下面的代码:

FileOutputStream oFile = new FileOutputStream(file, "a.properties");
pro.store(oFile, "Comment");
oFile.close();
  • 如果comments不为空,保存后的属性文件第一行会是#comments,表示注释信息;如果为空则没有注释信息。
  • 注释信息后面是属性文件的当前保存时间信息。

getProperty/setProperty

这两个方法是分别是获取和设置属性信息。

实际代码如下:

name=root
pass=liu

读取db.properties属性列表。代码如下:

public class PropertiesDemo01 {
	public static void main(String[] args) throws IOException {
pro.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));
		
		System.out.println(pro.getProperty("name"));
		System.out.println(pro.getProperty("pwd"));
		System.out.println(pro.setProperty("url"));
	}
}

collections工具类

在collections中有很多的方法,但是能用到的方法几乎很少,我们来看一下都有哪些方法。

void sort(List) //对 List 容器内的元素排序,按照升序进行排序。 
void shuffle(List) //对 List 容器内的元素进行随机排列 
void reverse(List) //对 List 容器内的元素进行逆续排列 
void fill(List, Object) //用一个特定的对象重写整个 List 容器 
int binarySearch(List, Object)//采用折半查找的方法查找特定对象

这些就是collections的常用方法,基本都是基于List的,应为只有List接口的实现类是有序可重复的,其他的Set和Map接口的实现类都是无序的,所以在这个工具类中我们经常用到的就是针对List接口的实现类的升序、随机、翻转、折半查找、特定对象重写等方法。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值