JavaSE学习笔记18:集合(四)

最爱琴女E 2020-11-11 17:05:52
学习 JAVASE 集合 笔记


集合(四)

HashMap和Hashtable的区别

HashMap的key可以为null吗?value呢?都可以为空!

package se3.themap;
import java.util.HashMap;
import java.util.Map;
public class HashMapTest03 {
public static void main(String[] args) {
Map map = new HashMap();
//HashMap集合允许key为null
map.put(null,null);
System.out.println(map.size());//1
//key重复的话,value会覆盖
map.put(null,100);
System.out.println(map.size());//1
//通过key获取value
System.out.println(map.get(null));//100
}
}

Hashtable的key可以为null吗?value呢?都不能为空!

package se3.themap;
import java.util.Hashtable;
import java.util.Map;
public class HashTableTest01 {
public static void main(String[] args) {
Map map = new Hashtable();
map.put(null,"阿波");
map.put(1,null);
}
}
  1. Hashtable和HashMap一样,底层都是哈希表数据结构
  2. Hashtable方法都带有synchronized:线程安全的
  3. Hashtable的初始化容量是11,默认加载因子是0.75
  4. Hashtable的扩容:原容量*2再+1

Properties

​ 目前只需要掌握Properties属性类对象的相关方法即可

​ Properties是一个Map集合,继承Hashtable,Properties的key和value都是String类型

​ Properties被称为属性类对象

​ Properties是线程安全的

package se3.themap;
import java.util.Properties;
public class PropertiesTest01 {
public static void main(String[] args) {
//创建一个Properties对象
Properties pro = new Properties();
//需要掌握Properties的两个方法,一个存,一个取
pro.setProperty("url","jdbc:mysql://localhost:3306/bjpowernode");
pro.setProperty("driver","com.mysql.jdbc.Driver");
pro.setProperty("username","root");
pro.setProperty("password","123");
//通过key获取value
String url = pro.getProperty("url");
String driver = pro.getProperty("driver");
String username = pro.getProperty("username");
String password = pro.getProperty("password");
System.out.println(url);//jdbc:mysql://localhost:3306/bjpowernode
System.out.println(driver);//com.mysql.jdbc.Driver
System.out.println(username);//root
System.out.println(password);//123
}
}

TreeSet

  1. TreeSet集合底层实际上是一个TreeMap
  2. TreeMap集合底层是一个二叉树
  3. 放到TreeSet集合中的元素,等同于放到TreeMap集合key部分了
  4. TreeSet集合中的元素:无序不可重复,但是可以按照元素的大小顺序自动排序,称为可排序集合。
package se3.set;
import java.util.TreeSet;
public class TreeSetTest02 {
public static void main(String[] args) {
//创建TreeSet集合
TreeSet<String> ts = new TreeSet<>();
//添加String元素
ts.add("钱七");
ts.add("张三");
ts.add("赵六");
ts.add("李四");
ts.add("王五");
//遍历
for (String s : ts){
//按照字典顺序,升序
System.out.print(s + " ");
}//张三 李四 王五 赵六 钱七
System.out.println();
TreeSet<Integer> ts2 = new TreeSet<>();
ts2.add(100);
ts2.add(200);
ts2.add(900);
ts2.add(800);
ts2.add(600);
ts2.add(10);
for (Integer elt : ts2){
//升序
System.out.print(elt + " ");
}//10 100 200 600 800 900
}
}

关于自定义类型排序

对自定义的类型来说,TreeSet可以排序吗?不行

  1. 以下程序中对于Person类型来说,无法排序。因为没有指定Person对象之间的比较规则
  2. 谁大谁小并没有说明
  3. 出现异常的原因是:Person类没有实现java.lang.Comparable接口。
package se3.set;
import java.util.TreeSet;
public class TreeSetTest03 {
public static void main(String[] args) {
Person p1 = new Person(32);
Person p2 = new Person(20);
Person p3 = new Person(30);
Person p4 = new Person(25);
//添加元素
TreeSet<Person> persons = new TreeSet<>();
persons.add(p1);
persons.add(p2);
persons.add(p3);
persons.add(p4);
//遍历
for (Person p : persons){
System.out.print(p + " ");
}
/**运行结果:
* Exception in thread "main" java.lang.ClassCastException: se3.set.Person cannot be cast to java.lang.Comparable
* at java.util.TreeMap.compare(TreeMap.java:1294)
* at java.util.TreeMap.put(TreeMap.java:538)
* at java.util.TreeSet.add(TreeSet.java:255)
* at se3.set.TreeSetTest03.main(TreeSetTest03.java:18)
*/
}
}
class Person{
int age;
public Person(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" + "age=" + age + '}';
}
}

自定义规则后如下:

package se3.set;
import java.util.TreeSet;
public class TreeSetTest04 {
public static void main(String[] args) {
Person2 p1 = new Person2(32);
Person2 p2 = new Person2(20);
Person2 p3 = new Person2(30);
Person2 p4 = new Person2(25);
//添加元素
TreeSet<Person2> persons = new TreeSet<>();
persons.add(p1);
persons.add(p2);
persons.add(p3);
persons.add(p4);
//遍历
for (Person2 p : persons){
System.out.println(p);
}
/**
* 运行结果:
* Person{age=20}
* Person{age=25}
* Person{age=30}
* Person{age=32}
*/
}
}
/*
放在TreeSet集合中元素需要实现java.lang.Comparable接口
并且实现CompareTo方法,equals可以不写
*/
class Person2 implements Comparable<Person2>{
int age;
public Person2(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" + "age=" + age + '}';
}
//需要在这个方法中编写比较的逻辑,或者说比较的方法,按什么进行比较
//k.compareTo(t.key)
//拿着参数k和集合中的每一个k进行比较,返回值可能是>0 <0 =0
//比较规则是由程序员指定的,例如按照年龄升序或者降序
@Override
public int compareTo(Person2 p) {//p1.compareTO(p2)
//this就是p1
//p是p2
//p1和p2比较的时候,就是this和p比较
/*
int age1 = this.age;
int age2 = p.age;
if(age1 == age2){
return 0;
} else if(age1 > age2){
return 1;
} else{
return -1;
}
*/
//简写
return this.age - p.age;
}
}

关于比较规则

怎么写?先按照年龄升序,如果年龄一样再按照姓名升序,例子如下:

package se3.set;
import java.util.TreeSet;
//先按照年龄升序,如果年龄一样再按照姓名升序
public class TreeSetTest05 {
public static void main(String[] args) {
TreeSet<Vip> vips = new TreeSet<>();
vips.add(new Vip("a阿波",20));
vips.add(new Vip("b阿波",20));
vips.add(new Vip("波波",18));
vips.add(new Vip("小波",17));
for (Vip vip : vips){
System.out.println(vip);
}
/**
* 输出结果:
* Vip{name='小波', age=17}
* Vip{name='波波', age=18}
* Vip{name='a阿波', age=20}
* Vip{name='b阿波', age=20}
*/
}
}
class Vip implements Comparable<Vip>{
String name;
int age;
public Vip(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Vip{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
/*
compareTo方法的返回值很重要:
返回0表示相同,value会覆盖
返回>0,会继续在右子树上找【10-9=1,1>0的说明左边这个数字比较大,所以在右子树上找】
返回<0,会继续在左子树上找
*/
@Override
public int compareTo(Vip v) {
if(this.age == v.age){
//年龄相同时按照名字排序
//名字是String类型,可以直接比,调用compareTo完成比较
return this.name.compareTo(v.name);
} else {
//年龄不一样
return this.age - v.age;
}
}
}

自平衡二叉树数据结构

TreeSet/TreeM是自平衡二叉树,遵循左小右大原则存放(存放的时候要进行比较)

注意:存放的过程就是排序的过程,取出来就是自动按照大小顺序排列

100 200 50 60 80 120 140 130 135 180 666 40 55存放后如下图

遍历二叉树的时候有三种方式

  1. 前序遍历:根左右
  2. 中序遍历:左根右
  3. 后序遍历:左右根

TreeSet集合/TreeMap集合采用的是:中序遍历

Iterator迭代器采用的是中序遍历方式(左根右)

中序遍历

采用中序遍历取出:

40 50 55 60 80 100 120 140 130 135 180 200 666

比较器方式实现TreeSet排序

package se3.set;
import java.util.Comparator;
import java.util.TreeSet;
/*
TreeSet集合中元素可排序的第二种方式:使用比较器的方式
*/
public class TreeSetTest06 {
public static void main(String[] args) {
//创建TreeSet集合的时候,需要使用这个比较器
//TreeSet<WuGui> wuGuis = new TreeSet<>();//这样不行,没有通过构造方法传递一个比较器进去
//给构造方法传递一个比较器
TreeSet<WuGui> wuGuis = new TreeSet<>(new WuGuiComparator());
wuGuis.add(new WuGui(1000));
wuGuis.add(new WuGui(800));
wuGuis.add(new WuGui(810));
for (WuGui wuGui : wuGuis){
System.out.println(wuGui);
}
/**
* 输出结果:
* 乌龟[age=800]
* 乌龟[age=810]
* 乌龟[age=1000]
*/
}
}
//乌龟
class WuGui{
int age;
public WuGui(int age) {
this.age = age;
}
@Override
public String toString() {
return "乌龟[" +
"age=" + age +
']';
}
}
//单独在这里编写一个比较器
//比较器实现java.util.Comparator接口。(Comparable是java.lang包下的,Comparator是java.util包下的)
class WuGuiComparator implements Comparator<WuGui>{
@Override
public int compare(WuGui o1, WuGui o2) {
//指定比较规则,按照年龄排序
return o1.age - o2.age;
}
}

匿名内部类方式实现TreeSet排序

package se3.set;
import java.util.Comparator;
import java.util.TreeSet;
public class TreeSetTest06 {
public static void main(String[] args) {
//TreeSet<WuGui> wuGuis = new TreeSet<>(new WuGuiComparator());
//使用匿名内部类的方式
TreeSet<WuGui> wuGuis = new TreeSet<>(new Comparator<WuGui>() {
@Override
public int compare(WuGui o1, WuGui o2) {
return o1.age - o2.age;
}
});
wuGuis.add(new WuGui(1000));
wuGuis.add(new WuGui(800));
wuGuis.add(new WuGui(810));
for (WuGui wuGui : wuGuis){
System.out.println(wuGui);
}
/**
* 输出结果:
* 乌龟[age=800]
* 乌龟[age=810]
* 乌龟[age=1000]
*/
}
}
//乌龟
class WuGui{
int age;
public WuGui(int age) {
this.age = age;
}
@Override
public String toString() {
return "乌龟[" +
"age=" + age +
']';
}
}

结论

放到TreeSet或者TreeMap集合key部分的元素要想做到排序,包括两种方式:

  1. 放在集合中元素实现java.lang.Comparable接口
  2. 在构造TreeSet或者TreeMap集合的时候给它传一个比较器对象

Comparable和Comparator怎么选择呢?

当比较规则不会发生改变的时候,或者说当比较规则只有1个的时候,建议使用Comparable接口。

如果比较规则有多个,并且需要多个比较规则之间频繁切换,建议使用Comparator接口。

Collections工具类

package se3.collection;
import java.util.*;
/*
java.util.Collection 集合接口
java.util.Collections 集合工具类,方便集合的操作。
*/
public class CollectionsTest01 {
public static void main(String[] args) {
//ArrayList集合不是线程安全的
List<String> list = new ArrayList<>();
//变成线程安全的
Collections.synchronizedList(list);
list.add("abf");
list.add("abx");
list.add("abc");
list.add("abe");
//排序
Collections.sort(list);
for (String s : list){
System.out.print(s + " ");
}//abc abe abf abx
System.out.println();
List<WuGui2> wuGui2s = new ArrayList<>();
wuGui2s.add(new WuGui2(1000));
wuGui2s.add(new WuGui2(8000));
//注意:对List集合中元素排序,需要保证List集合中的元素实现Comparable接口
Collections.sort(wuGui2s);
for (WuGui2 wuGui2 : wuGui2s){
System.out.println(wuGui2);
}
/*
乌龟[age=1000]
乌龟[age=8000]
*/
//Set集合排序
Set<String> set = new HashSet<>();
set.add("king");
set.add("kingsoft");
set.add("king2");
set.add("king1");
//将Set集合转换成List集合
List<String> mylist = new ArrayList<>(set);
Collections.sort(mylist);
for (String s : mylist){
System.out.print(s + " ");
}//king king1 king2 kingsoft
}
}
class WuGui2 implements Comparable<WuGui2>{
int age;
public WuGui2(int age) {
this.age = age;
}
@Override
public int compareTo(WuGui2 o) {
return this.age - o.age;
}
@Override
public String toString() {
return "乌龟[" +
"age=" + age +
']';
}
}
版权声明
本文为[最爱琴女E]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/Sona-36D/p/13959494.html

  1. 【计算机网络 12(1),尚学堂马士兵Java视频教程
  2. 【程序猿历程,史上最全的Java面试题集锦在这里
  3. 【程序猿历程(1),Javaweb视频教程百度云
  4. Notes on MySQL 45 lectures (1-7)
  5. [computer network 12 (1), Shang Xuetang Ma soldier java video tutorial
  6. The most complete collection of Java interview questions in history is here
  7. [process of program ape (1), JavaWeb video tutorial, baidu cloud
  8. Notes on MySQL 45 lectures (1-7)
  9. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  10. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  11. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  12. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  13. 【递归,Java传智播客笔记
  14. [recursion, Java intelligence podcast notes
  15. [adhere to painting for 386 days] the beginning of spring of 24 solar terms
  16. K8S系列第八篇(Service、EndPoints以及高可用kubeadm部署)
  17. K8s Series Part 8 (service, endpoints and high availability kubeadm deployment)
  18. 【重识 HTML (3),350道Java面试真题分享
  19. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  20. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  21. [re recognize HTML (3) and share 350 real Java interview questions
  22. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  23. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  24. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  25. RPC 1: how to develop RPC framework from scratch
  26. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  27. RPC 1: how to develop RPC framework from scratch
  28. 一次性捋清楚吧,对乱糟糟的,Spring事务扩展机制
  29. 一文彻底弄懂如何选择抽象类还是接口,连续四年百度Java岗必问面试题
  30. Redis常用命令
  31. 一双拖鞋引发的血案,狂神说Java系列笔记
  32. 一、mysql基础安装
  33. 一位程序员的独白:尽管我一生坎坷,Java框架面试基础
  34. Clear it all at once. For the messy, spring transaction extension mechanism
  35. A thorough understanding of how to choose abstract classes or interfaces, baidu Java post must ask interview questions for four consecutive years
  36. Redis common commands
  37. A pair of slippers triggered the murder, crazy God said java series notes
  38. 1、 MySQL basic installation
  39. Monologue of a programmer: despite my ups and downs in my life, Java framework is the foundation of interview
  40. 【大厂面试】三面三问Spring循环依赖,请一定要把这篇看完(建议收藏)
  41. 一线互联网企业中,springboot入门项目
  42. 一篇文带你入门SSM框架Spring开发,帮你快速拿Offer
  43. 【面试资料】Java全集、微服务、大数据、数据结构与算法、机器学习知识最全总结,283页pdf
  44. 【leetcode刷题】24.数组中重复的数字——Java版
  45. 【leetcode刷题】23.对称二叉树——Java版
  46. 【leetcode刷题】22.二叉树的中序遍历——Java版
  47. 【leetcode刷题】21.三数之和——Java版
  48. 【leetcode刷题】20.最长回文子串——Java版
  49. 【leetcode刷题】19.回文链表——Java版
  50. 【leetcode刷题】18.反转链表——Java版
  51. 【leetcode刷题】17.相交链表——Java&python版
  52. 【leetcode刷题】16.环形链表——Java版
  53. 【leetcode刷题】15.汉明距离——Java版
  54. 【leetcode刷题】14.找到所有数组中消失的数字——Java版
  55. 【leetcode刷题】13.比特位计数——Java版
  56. oracle控制用户权限命令
  57. 三年Java开发,继阿里,鲁班二期Java架构师
  58. Oracle必须要启动的服务
  59. 万字长文!深入剖析HashMap,Java基础笔试题大全带答案
  60. 一问Kafka就心慌?我却凭着这份,图灵学院vip课程百度云