Java学习-Day20(Set、Map、HashTable、Properties)

Set接口实现类——LinkedHashSet(HashSet的子类)

  • 基本介绍

    1. LinkedHashSet是 HashSet的子类
    2. LinkedHashSet底层是一个 LinkedHashMap(HashMap的子类),底层维护了一个数组+双向链表
    3. LinkedHashSet根据元素的 hashCode值来决定元素的存储位置,同时使用链表维护元素的次序(图),这使得元素看起来是以插入顺序保存的。(添加顺序和取出顺序一致)
    4. LinkedHashSet不允许添重复元素
      在这里插入图片描述
/*
源码:
添加第一次时,直接将数组table扩容到16,存放的结点类型是LinkedHashMap$Entry

数组是HashMap$Node[],存放的元素/数据是LinkedHashMap$Entry


*/

Map接口

Map接口实现类的特点

  1. Map与Collection并列存在。用于保存具有映射关系的数据:Key-Value
  2. Map 中的key 和 value可以是任何引用类型的数据,会封装到HashMap$Node对象中
  3. Map中的key 不允许重复,原因和HashSet一样,前面分析过源码,key相同时,value值被新输入的值替换
  4. Map中的value可以重复
  5. Map 的key可以为 null, value也可以为null,注意key为null,只能有一个,value为null ,可以多个
  6. 常用String类作为Map的key
  7. key 和 value之间存在单向一对一关系,即通过指定的key 总能找到对应的value
  8. Map存放数据的key-value示意图,一对k-v是放在一个HashMap$Node中的,有因为Node实现了Entry 接口,有些书上也说一对k-v就是一个Entry(如图)[代码演示]

Map接口的常用方法

Map map = new HashMap();

//put:添加
map.put("鹿晗","关晓彤");

// remove:根据键删除映射关系
map.remove(null);
System.out.println("map=" + map);

// get: 根据键获取值
Object val = map.get("鹿晗");
System.out.println("val=" + val);//关晓彤

// size:获取元素个数
System.out.println("k-v=" + map.size());//1

// isEmpty:判断个数是否为 0
System.out.println(map.isEmpty());//F

// clear:清除 k-v
//map.clear();
System.out.println("map=" + map);//全都没了

// containsKey:查找键是否存在
System.out.println("结果=" + map.containsKey("hsp"));//T

Map接口六大遍历方式:

工具方法:

containsKey:查找键是否存在

keySet:获取所有的键

entrySet:获取所有关系k-v

values:获取所有的值

//第一组: 先取出 所有的 Key , 通过 Key 取出对应的 Value
Set keyset = map.keySet();

//(1) 增强 for
System.out.println("-----第一种方式-------");
for (Object key : keyset) {
System.out.println(key + "-" + map.get(key));
}

//(2) 迭代器
System.out.println("----第二种方式--------");
Iterator iterator = keyset.iterator();
while (iterator.hasNext()) {
Object key = iterator.next();
System.out.println(key + "-" + map.get(key));
}

//第二组: 把所有的 values 取出
Collection values = map.values();

//这里可以使用所有的 Collections 使用的遍历方法

//(1) 增强 for
System.out.println("---取出所有的 value 增强 for----");
for (Object value : values) {
System.out.println(value);
} 

//(2) 迭代器
System.out.println("---取出所有的 value 迭代器----");
Iterator iterator2 = values.iterator();
while (iterator2.hasNext()) {
Object value = iterator2.next();
System.out.println(value);
}

//第三组: 通过 EntrySet 来获取 k-v
Set entrySet = map.entrySet();

// EntrySet<Map.Entry<K,V>>
//(1) 增强 for
System.out.println("----使用 EntrySet 的 for 增强(第 3 种)----");

for (Object entry : entrySet) {
//将 entry 转成 Map.Entry
Map.Entry m = (Map.Entry) entry;
System.out.println(m.getKey() + "-" + m.getValue());
} 

//(2) 迭代器
System.out.println("----使用 EntrySet 的 迭代器(第 4 种)----");
Iterator iterator3 = entrySet.iterator();
while (iterator3.hasNext()) {
Object entry = iterator3.next();
//System.out.println(next.getClass());//HashMap$Node -实现-> Map.Entry (getKey,getValue)
//向下转型 Map.Entry
Map.Entry m = (Map.Entry) entry;
System.out.println(m.getKey() + "-" + m.getValue());
}

HashMap小结:

  1. Map接口的常用实现类:HashMap、Hashtable和Properties
  2. HashMap是 Map 接口使用频率最高的实现类。
  3. HashMap是以 key-val对的方式来存储数据(HashMap$Node类型)[案例Entry ]
  4. key不能重复,但是值可以重复,允许使用null键和null值。
  5. 如果添加相同的key,则会覆盖原来的key-val ,等同于修改.(key不会替换,val会替换)
  6. 与HashSet一样,不保证映射的顺序,因为底层是以hash表的方式来存储的.(jdk8的hashMap底层数组+链表+红黑树)
  7. HashMap没有实现同步,因此是线程不安全的,方法没有做同步互斥的操作,没有synchronized

HashMap底层机制及源码剖析

在这里插入图片描述

HashTable

  1. 存放的元素是键值对:即K-V

  2. hashtable的键和值都不能为null,否则会抛出NullPointerException

  3. hashTable使用方法基本上和HashMap一样

  4. hashTable是线程安全的(synchronized), hashMap 是线程不安全的

  5. 简单看下底层结构 HashTable的应用案例

在这里插入图片描述
在这里插入图片描述

Properties

  1. Properties类继承自Hashtable类并且实现了Map接口,也是使用一种键值对的形式来保存数据。
  2. 他的使用特点和Hashtable类似
  3. Properties还可以用于从 xoxx.properties文件中,加载数据到Properties类对象,并进行读取和修改
  4. 说明:工作后 Xxx.properties文件通常作为配置文件,这个知识点在IO流举例,有兴趣可先看文章
//老韩解读
//1. Properties 继承 Hashtable
//2. 可以通过 k-v 存放数据, 当然 key 和 value 不能为 null

//增加
Properties properties = new Properties();
//properties.put(null, "abc");//抛出 空指针异常
//properties.put("abc", null); //抛出 空指针异常
properties.put("john", 100);//k-v
properties.put("lucy", 100);
properties.put("lic", 100);
properties.put("lic", 88);//如果有相同的 key , value 被替换
System.out.println("properties=" + properties);

//通过 k 获取对应值
System.out.println(properties.get("lic"));//88

//删除
properties.remove("lic");
System.out.println("properties=" + properties);

//修改
properties.put("john", "约翰");
System.out.println("properties=" + properties);

开发中如何选择集合实现类

在这里插入图片描述

Collections工具类

  1. Collections是一个操作 Set、List和 Map等集合的工具类
  2. Collections中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作

排序操作:

  1. reverse(List):反转 List中元素的顺序

  2. shuffle(List):对List集合元素进行随机排序

  3. sort(List):根据元素的自然顺序对指定List 集合元素按升序排序

  4. sort(List,Comparator):根据指定的Comparator产生的顺序对List集合元素进行排序

  5. swap(List,int,int):将指定list集合中的i处元素和j处元素进行交换

  6. //创建 ArrayList 集合, 用于测试.
    List list = new ArrayList();
    list.add("tom");
    list.add("smith");
    list.add("king");
    list.add("milan");
    list.add("tom");
    
    // reverse(List): 反转 List 中元素的顺序
    Collections.reverse(list);
    System.out.println("list=" + list);
    
    // shuffle(List): 对 List 集合元素进行随机排序
    // for (int i = 0; i < 5; i++) {
    // Collections.shuffle(list);
    // System.out.println("list=" + list);
    // }
    
    // sort(List): 根据元素的自然顺序对指定 List 集合元素按升序排序
    Collections.sort(list);
    System.out.println("自然排序后");
    System.out.println("list=" + list);
    // sort(List, Comparator): 根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
    //我们希望按照 字符串的长度大小排序
    Collections.sort(list, new Comparator() {
    @Override
    public int compare(Object o1, Object o2) {
    //可以加入校验代码.
    return ((String) o2).length() - ((String) o1).length();
    }
    });
    System.out.println("字符串长度大小排序=" + list);
    
    // swap(List, int, int): 将指定 list 集合中的 i 处元素和 j 处元素进行交换
    //比如
    Collections.swap(list, 0, 1);
    System.out.println("交换后的情况");
    System.out.println("list=" + list);
    
    //Object max(Collection): 根据元素的自然顺序, 返回给定集合中的最大元素
    System.out.println("自然顺序最大元素=" + Collections.max(list));
     
    //Object max(Collection, Comparator): 根据 Comparator 指定的顺序, 返回给定集合中的最大元素
    //比如, 我们要返回长度最大的元素
    Object maxObject = Collections.max(list, new Comparator() {
    @Override
    public int compare(Object o1, Object o2) {
    return ((String)o1).length() - ((String)o2).length();
    }
    });
    System.out.println("长度最大的元素=" + maxObject);
    
    //Object min(Collection)
    //Object min(Collection, Comparator)
    //上面的两个方法, 参考 max 即可
    
    //int frequency(Collection, Object): 返回指定集合中指定元素的出现次数
    System.out.println("tom 出现的次数=" + Collections.frequency(list, "tom"));
    
    //void copy(List dest,List src): 将 src 中的内容复制到 dest 中
    ArrayList dest = new ArrayList();
    //为了完成一个完整拷贝, 我们需要先给 dest 赋值, 大小和 list.size()一样
    for(int i = 0; i < list.size(); i++) {
    dest.add("");
    } 
    //拷贝
    Collections.copy(dest, list);
    System.out.println("dest=" + dest);
    
    //boolean replaceAll(List list, Object oldVal, Object newVal): 使用新值替换 List 对象的所有旧值
    //如果 list 中, 有 tom 就替换成 汤姆
    Collections.replaceAll(list, "tom", "汤姆");
    System.out.println("list 替换后=" + list);
    
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晚来舟Mango

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值