--------------------------------------------------------------------------------------------莫听穿林打叶声,一蓑烟雨任平生--------------------------------------------------------------------------------------------

Java笔记day25

一、TreeSet集合练习
1、使用元素的自然顺序对元素进行排序
需求:使用TreeSet集合存储学生对象,根据学生的长度进行排序
先写学生类
public class Student implements Comparable<Student>{
private String name;
private int age;

public Student() {
}

public Student(String name, int age) {
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;
}

@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}

@Override
public int compareTo(Student o) {
//题目要求:按照姓名的长度进行排序
int i = this.name.length() - o.name.length(); //和前一个相比较
//姓名长度一样不代表姓名的内容一样
int i2 = i == 0 ? this.name.compareTo(o.name) : i;

//姓名的长度和内容一样,但是年龄可能不一样
//只有当姓名和年龄都一样的时候,才能判断是同一个人
int i3 = i2 == 0 ? this.age-o.age : i2;
return i3;
}
}
再写主要代码
import java.util.TreeSet;
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet<Student> ts = new TreeSet<Student>();

//创建学生对象
Student s1 = new Student("zhujiale",18);
Student s2 = new Student("caoxintao",17);
Student s3 = new Student("taohuagen",19);
Student s4 = new Student("zhangmi",16);
Student s5 = new Student("caoxintao",19);

//将学生对象添加到集合
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);

for(Student s : ts){
System.out.println(s);
}
//如果不在Student类中实现Comparable接口和重写其方法
//这里会报类型转换异常的错误
}
}
2、使用TreeSet提供的Comparator(比较器接口)进行排序
Student2类
public class Student2 {
private String name;
private int age;

public Student2() {
}

public Student2(String name, int age) {
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;
}

@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
主要代码
根据创建 set 时提供的 Comparator 进行排序
具体取决于使用的构造方法。
import java.util.Comparator;
import java.util.TreeSet;
public class TreeSetDemo2 {
public static void main(String[] args) {
//MyComparetor mc = new MyComparetor(); 这里也可以通过创建一个MyComparator类来实现Comparator
//TreeSet<Student2> ts = new TreeSet<Student2>(mc); 下面的写法是使用了匿名内部类
//这里和上面自然排序的区别在于,自然排序是使用没有参数的构造方法,而比较器是由参数的构造方法
//另外无参实现的是Comparable,有参实现的是Comparator
TreeSet<Student2> ts = new TreeSet<Student2>(new Comparator<Student2>() {
@Override
public int compare(Student2 o1, Student2 o2) {
//题目要求:按照姓名的长度进行排序
int i = o1.getName().length() - o2.getName().length();
//姓名长度一样不代表姓名的内容一样
int i2 = i == 0 ? o1.getName().compareTo(o2.getName()) : i;
//姓名的长度和内容一样,但是年龄可能不一样
//只有当姓名和年龄都一样的时候,才能判断是同一个人
int i3 = i2 == 0 ? o1.getAge()-o2.getAge() : i2;
return i3;
}
});

//创建学生对象
Student2 s1 = new Student2("zhujiale",18);
Student2 s2 = new Student2("caoxintao",17);
Student2 s3 = new Student2("taohuagen",19);
Student2 s4 = new Student2("zhangmi",16);
Student2 s5 = new Student2("caoxintao",19);

//将学生对象添加到集合
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);

for(Student2 s : ts){
System.out.println(s);
}
}
}
3、TreeSet底层是红黑树,由红黑树保证元素唯一和有序
举例
import java.util.TreeSet;
public class TreeSetDemo3 {
public static void main(String[] args) {
TreeSet<Integer> ts = new TreeSet<>();

ts.add(32);
ts.add(18);
ts.add(15);
ts.add(24);
ts.add(30);
ts.add(32);
ts.add(15);

for(Integer i : ts){
System.out.println(i);
}
//输出的时候是去重且排序好的
//存储数据时,在底层的红黑二叉树中,32第一个插入作为根节点,
//比32大的放右边,比32小的放左边,各个节点同理,遇到相同的覆盖
//遍历的时候采用中序遍历(左根右)
//这样输出的时候就是从小到大排序好的去重的集合
}
}
4、TreeSet集合存储自定义对象并遍历
如果对象的成员变量值相同即为同一个对象
按照年龄进行从大到小进行排序(以第二题中的Student2为对象)
import java.util.Comparator;
import java.util.TreeSet;
public class TreeSetDemo4 {
public static void main(String[] args) {
TreeSet<Student2> student2s = new TreeSet<Student2>(new Comparator<Student2>() {
@Override
public int compare(Student2 o1, Student2 o2) {
//按照年龄进行从大到小进行排序
//如果是o1-o2就是从小到大排序
int i = o2.getAge() - o1.getAge();
//比较隐含条件,年龄一样,姓名不一定一样
int i2 = i == 0 ? o1.getName().compareTo(o2.getName()) : i;
return i2;
}
});

//创建学生对象
Student2 s1 = new Student2("小李", 18);
Student2 s2 = new Student2("小赵", 18);
Student2 s3 = new Student2("大龙", 16);
Student2 s4 = new Student2("小龙", 19);

//将学生对象添加到集合中
student2s.add(s1);
student2s.add(s2);
student2s.add(s3);
student2s.add(s4);

for(Student2 s : student2s){
System.out.println(s);
}
}
}
6、 编写一个程序,获取10个1至20的随机数,要求随机数不能重复。
import java.util.Random;
import java.util.TreeSet;
public class TreeSetDemo5 {
public static void main(String[] args) {
//创建随机数对象
Random random = new Random();
TreeSet<Integer> integers = new TreeSet<>();
while (true){
if(integers.size()==10){
break;
}
//生成随机数
int number = random.nextInt(20) + 1;
integers.add(number);
}
System.out.println(integers);
}
}
7、 键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),
按照总分从高到低输出到控制台,假设班级没有重名的
Student3类
public class Student3 {
private String name;
//学科
private int chinese;
private int math;
private int english;

public Student3() {
}

public Student3(String name, int chinese, int math, int english) {
this.name = name;
this.chinese = chinese;
this.math = math;
this.english = english;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getChinese() {
return chinese;
}

public void setChinese(int chinese) {
this.chinese = chinese;
}

public int getMath() {
return math;
}

public void setMath(int math) {
this.math = math;
}

public int getEnglish() {
return english;
}

public void setEnglish(int english) {
this.english = english;
}

public int getSum(){
return chinese + math + english;
}

@Override
public String toString() {
return "Student3{" +
"name='" + name + '\'' +
", chinese=" + chinese +
", math=" + math +
", english=" + english +
'}';
}
}
主要代码
import java.util.Comparator;
import java.util.TreeSet;
import java.util.Scanner;
public class TreeSetDemo6 {
public static void main(String[] args) {
//创建一个TreeSet集合对象,匿名内部类的形式实现Comparator接口
TreeSet<Student3> ts = new TreeSet<>(new Comparator<Student3>() {
@Override
public int compare(Student3 o1, Student3 o2) {
//按照总分从高到低
int i = o2.getSum() - o1.getSum();
//总分一样,语文成绩不一定一样
int i2 = i == 0 ? o1.getChinese() - o2.getChinese() : i;
//总分一样,语文成绩一样,数学成绩不一定一样
int i3 = i2 == 0 ? o1.getMath() - o2.getMath() : i2;
//总分一样,语文成绩一样,数学成绩一样,英语成绩不一定一样
int i4 = i3 == 0 ? o1.getEnglish() - o2.getEnglish() : i3;
//总分一样,语文成绩一样,数学成绩一样,英语成绩一样,姓名不一定一样
int i5 = i4 == 0 ? o1.getName().compareTo(o2.getName()) : i4;
return i5;
}
});

//创建Scanner对象
Scanner sc = new Scanner(System.in);

for (int i = 1; i < 6; i++) {
System.out.println("请输入第" + i + "个学生的姓名:");
String name = sc.next();
System.out.println("请输入" + name + "的语文成绩:");
int chinese = sc.nextInt();
System.out.println("请输入" + name + "的数学成绩:");
int math = sc.nextInt();
System.out.println("请输入" + name + "的英语成绩:");
int english = sc.nextInt();

//创建学生对象,将输入的值赋给学生对象的成员变量
Student3 student = new Student3();
student.setName(name);
student.setChinese(chinese);
student.setMath(math);
student.setEnglish(english);

//将学生对象添加到集合中
ts.add(student);

if (i == 5) {
System.out.println("所有的学生信息录入完毕!");
}
}
System.out.println("===========================================");
System.out.println("学生信息如下:");
System.out.println("姓名\t语文成绩\t数学成绩\t英语成绩\t总成绩");
//遍历学生信息
for (Student3 student3 : ts) {
System.out.println(student3.getName() + "\t" + student3.getChinese() + "\t"
+ student3.getMath() + "\t" + student3.getEnglish() + "\t" + student3.getSum());
}
}
}

二、map接口概述
Map接口概述
将键映射到值的对象
一个映射不能包含重复的键
每个键最多只能映射到一个值
举例:
<K, V> 键值对
1001 喜羊羊
1001 懒洋洋(不允许)
1002 喜羊羊
在Map集合中,Key的值不能重复。
Map接口与Collection接口有什么区别?
1、Map接口与Collection接口是平级的关系,不存在继承关系,都是属于util包下面的
2、Map集合中存储的元素都是成对出现的,Map元素的键是唯一的,值是可以重复的
3、Collection接口中的元素都是单独出现的,Collection接口下面有个子接口Set元素是唯一的
List集合中的元素是可以重复的
添加功能:
V put(K key, V value)将指定的值与该映射中的指定键相关联(可选操作)。
举例:map.put(1001, "朱佳乐");

删除功能:
void clear()从该map中删除所有的映射(可选操作)。
V remove(Object key)如果存在(从可选的操作),从该地图中删除一个键的映射

判断功能:
boolean containsKey(Object key)如果此映射包含指定键的映射,则返回true 。
boolean containsValue(Object value)如果此映射将一个或多个键映射到指定的值,则返回true 。
boolean isEmpty()如果此map不包含键值映射,则返回 true 。

获取功能:
Set<Map.Entry<K,V>> entrySet()返回此map中包含的映射的Set视图。
V get(Object key)返回到指定键所映射的值,或null如果此映射包含该键的映射。
Set<K> keySet()返回此map中包含的键的Set视图。
Collection<V> values()返回此地图中包含的值的Collection视图。

长度功能:
int size()返回此地图中键值映射的数量。
获取功能:
V get(Object key)返回到指定键所映射的值,或null如果此映射包含该键的映射。
Set<K> keySet()返回此map中包含的键的Set视图。
Collection<V> values()返回此地图中包含的值的Collection视图。

import java.util.Collection;
import java.util.HashMap;
import java.util.Set;
public class MapDemo1 {
public static void main(String[] args) {
//创建一个Map集合对象
HashMap<String, String> ssh = new HashMap<>();

//添加元素
//V put(K key, V value)将指定的值与该映射中的指定键相关联(可选操作)。
//返回的是该键对应被覆盖之前的值
//多次添加同一个key的映射的时候,key只有一个,值被覆盖。

//System.out.println(ssh.put("邓超", "孙俪")); Null
//System.out.println(ssh.put("邓超", "孙俪")); 孙俪
//System.out.println(ssh.put("邓超", "孙俪2")); 孙俪
//System.out.println(ssh.put("邓超", "孙俪3")); 孙俪2

ssh.put("邓超", "孙俪");
ssh.put("吴京", "谢楠");
ssh.put("张杰", "谢娜");
ssh.put("杨某人", "马凡舒");
System.out.println(ssh); //输出的时候会按照Key字典排序方法自动排序

//注:如果在赋值过程中出现了相同的键,那么这个键值对就不会参与排序,还是放在它原本输入的顺序上

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

//void clear()从该map中删除所有的映射(可选操作)。
//ssh.clear(); //输出是{}
//System.out.println(ssh);

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

//V remove(Object key)如果存在(从可选的操作),从该地图中删除一个键的映射
//key不存在的时候不会报错,这时输出的是null
//返回的是被删除的key对应的值,并且从map集合中移除
System.out.println(ssh.remove("杨某人")); //返回的是删除的Key对应的Value
System.out.println(ssh);

//boolean containsKey(Object key)如果此映射包含指定键的映射,则返回true 。
System.out.println("===================================");
System.out.println(ssh.containsKey("邓超")); //true
System.out.println(ssh.containsKey("杨某人")); //false

// boolean containsValue(Object value)如果此映射将一个或多个键映射到指定的值,则返回true 。
System.out.println(ssh.containsValue("孙俪")); //true
System.out.println(ssh.containsValue("马凡舒")); //false

System.out.println("===================================");
//boolean isEmpty()如果此map不包含键值映射,则返回 true 。
System.out.println(ssh.isEmpty()); //false

//int size()返回此地图中键值映射的数量。
System.out.println("map集合中的键值对个数:" + ssh.size()); //3

//V get(Object key)返回到指定键所映射的值,或null
//如果map中不包含该键,返回的是null
System.out.println(ssh.get("邓超")); //孙俪
System.out.println(ssh.get("杨某人")); //null
System.out.println("===================================");

//Set<K> keySet()返回此map中包含的键的Set视图。
Set<String> strings = ssh.keySet();
for(String s : strings){
System.out.println(s);
}
//输出依旧按照字典排序
System.out.println("===================================");

//Collection<V> values()返回此地图中包含的值的Collection视图。
Collection<String> values = ssh.values();
for (String s : values){
System.out.println(s);
}
//输出是按照Key的排序对应的键值输出的
}
}

三、Map集合遍历
Map集合遍历有两种方式,举例如下
注意:只有直接输出的时候才会自动排序,如果是下面的遍历则不会排序,而是直接按照存储顺序输出
如果遍历的集合中有覆盖,那么输出时被覆盖的那个键值对的位置顺序是不会改变的
1、HashMap<String, String>
import java.util.HashMap;
import java.util.Set;
public class MapDemo3 {
public static void main(String[] args) {
HashMap<String, String> ssh = new HashMap<>();

//添加元素
ssh.put("梁山伯", "祝英台");
ssh.put("罗密欧", "朱丽叶");
ssh.put("杰克", "露丝");
ssh.put("周瑜", "大乔");
ssh.put("贾宝玉", "林黛玉");

//方式一
//根据键找值
// 1、获取Map集合中所有映射的键的Set集合
// 2、遍历键的集合,根据键找对应的值
// 3、输出

//获取Map集合中所有映射的键的Set集合
Set<String> keySet = ssh.keySet();
for (String key : keySet) {
String value = ssh.get(key);
System.out.println(key + "---" + value);

//方式二
//根据键值对对象找键和值
// 1、获取所有键值对的集合
// 2、遍历获取每一个键值对,得到每一个键值对对象
// 3、根据获取到的每一个键值对对象,来进一步获取键和值

//获取所有键值对的集合
Set<Map.Entry<String, String>> entries = ssh.entrySet();
for (Map.Entry<String, String> keyValue : entries) {
//HashMap中重写了getKey()和getValue()方法
String key = keyValue.getKey();
String value = keyValue.getValue();
System.out.println(key + "---" + value);
}
}
}
}
2、HashMap<Integer ,String>
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MapDemo5 {
public static void main(String[] args) {
//创建Map集合对象
HashMap<Integer, String> map = new HashMap<>();

map.put(1001, "宋轶");
map.put(1002, "毛晓彤");
map.put(1003, "王冰冰");
map.put(1004, "马凡舒");

//遍历集合
//按照数字的字典排序输出
System.out.println("=======方式1:根据键找值========");
Set<Integer> keys = map.keySet();

for (Integer key : keys) {
String value = map.get(key);
System.out.println(key + "---" + value);
}

System.out.println("=======方式2:根据键值对找键和值========");
Set<Map.Entry<Integer, String>> keyValue = map.entrySet();
for (Map.Entry<Integer, String> kv : keyValue) {
Integer key = kv.getKey();
String value = kv.getValue();
System.out.println(key + "---" + value);
}
}
}
3、HashMap<String,Student>

先创建Student4类
import java.util.Objects;
public class Student4 {
private String name;
private int age;

public Student4() {
}

public Student4(String name, int age) {
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;
}

@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}

/*
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student4 student4 = (Student4) o;
return age == student4.age &&
Objects.equals(name, student4.name);
}

@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
*/
遍历实现
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MapDemo6 {
public static void main(String[] args) {
//创建map集合对象
HashMap<String, Student4> map = new HashMap<>();

//创建4个学生对象
Student4 s1 = new Student4("刘备", 18);
Student4 s2 = new Student4("关羽", 17);
Student4 s3 = new Student4("张飞", 19);
Student4 s4 = new Student4("吕布", 19);

//向map集合中添加键值对
map.put("双股剑", s1);
map.put("青龙偃月刀", s2);
map.put("丈八蛇矛", s3);
map.put("方天画戟", s4);

//获取键值对遍历
Set<Map.Entry<String, Student4>> entries = map.entrySet();
for (Map.Entry<String, Student4> keyValue : entries) {
String key = keyValue.getKey();
Student4 value = keyValue.getValue();
System.out.println(key + "---" + value);
}
}
}

4、HashMap<Student,String>

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MapDemo7 {
public static void main(String[] args) {
//继续使用上面的Student4
HashMap<Student4, String> map = new HashMap<>();

//创建学生对象
Student4 s1 = new Student4("貂蝉", 17);
Student4 s2 = new Student4("西施", 18);
Student4 s3 = new Student4("杨玉环", 16);
Student4 s4 = new Student4("王昭君", 19);
Student4 s5 = new Student4("貂蝉", 17);

//将元素添加到集合中
map.put(s1, "1111");
map.put(s2, "2222");
map.put(s3, "3333");
map.put(s4, "4444");
map.put(s5, "5555");

//遍历
Set<Map.Entry<Student4, String>> entries = map.entrySet();
for (Map.Entry<Student4, String> kv : entries) {
Student4 key = kv.getKey();
String value = kv.getValue();
System.out.println(key + "---" + value);
}
//这里的输出没有去重,有两个貂蝉
//去Student4中重写equals和hashCode方法就可以解决这个问题
}
}

四、LinkedHashMap(hashMap的子类)
LinkedHashMap:
public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>
哈希表和链表实现的Map接口,具有可预测的迭代次序。
哈希表保证元素的唯一,保证的是key的唯一
链表保证的是有序,存储和取出的顺序一致。

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
public class LinkedHashMapDemo {
public static void main(String[] args) {
LinkedHashMap<String, String> linkedMap = new LinkedHashMap<>();

//添加元素到集合中
linkedMap.put("3213", "hello");
linkedMap.put("1234", "world");
linkedMap.put("3456", "java");
linkedMap.put("1234", "hadoop");
linkedMap.put("3456", "spark");
linkedMap.put("4567", "hello");

//遍历
Set<Map.Entry<String, String>> entries = linkedMap.entrySet();
for (Map.Entry<String, String> kv : entries) {
String key = kv.getKey();
String value = kv.getValue();
System.out.println(key + "---" + value);
}
}
}

五、TreeMap
TreeMap:底层数据结构是红黑树
1、TreeMap<String,String>
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class TreeMapDemo1 {
public static void main(String[] args) {
//创建集合对象
TreeMap<String, String> map = new TreeMap<>();

//添加元素到集合中
map.put("hello", "你好");
map.put("java", "面向对象编程的语言");
map.put("hadoop", "适合海量数据存储的分布式计算和分布式存储的平台");
map.put("hive", "是数据仓库建模工具之一");
map.put("java", "面向对象编程的语言2");

//遍历
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> kv : entries) {
String key = kv.getKey();
String value = kv.getValue();

System.out.println(key + "--" + value);
}
}
}
2、TreeMap<Student,String>
继续使用上面的Student4

import java.util.Comparator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class TreeMapDemo2 {
public static void main(String[] args) {
//创建TreeMap对象
//要么Student4实现Comparable接口,要么用Comparator比较器
//否则会报错,类型转换错误
TreeMap<Student4, String> map = new TreeMap<>(new Comparator<Student4>() {
@Override
public int compare(Student4 o1, Student4 o2) {
//年龄
int i = o1.getAge()-o2.getAge();
//姓名
int i2 = i == 0 ? o1.getName().compareTo(o2.getName()) : i;
return i2;
}
});

//创建学生对象
Student4 s1 = new Student4("耳根", 18);
Student4 s2 = new Student4("忘语", 19);
Student4 s3 = new Student4("肘子", 20);
Student4 s4 = new Student4("唐家三少", 17);
Student4 s5 = new Student4("耳根", 18);

//添加元素到集合中
map.put(s1, "仙逆");
map.put(s2, "凡人修仙传");
map.put(s3, "大王饶命");
map.put(s4, "斗罗大陆");
map.put(s5, "仙逆");

//遍历
Set<Map.Entry<Student4, String>> entries = map.entrySet();
for (Map.Entry<Student4, String> entry : entries) {
Student4 key = entry.getKey();
String value = entry.getValue();
System.out.println(key + "---" + value);
}
}
}

六、Map集合案例
"aababcabcdabcde",获取键盘录入字符串中每一个字母出现的次数
要求结果:a(5)b(4)c(3)d(2)e(1)

1、键盘录入一个字符串
2、使用TreeMap集合对象
键:Character
值:Integer
3、将字符串转换从字符数组
4、遍历字符数组获取每一个字符
5、拿着获取到的字符去集合中键去找,看看有没有这个键
如果没有,就把这个字符当作key,value值为1进行存储
如果有,就把该字符对应的值+1,重新存储到集合中
6、定义一个StringBuffer作为拼接
7、遍历集合,得到键和值,按照指定的输出对进行拼接a(5)b(4)c(3)d(2)e(1)
8、将StringBuffer转换成字符串输出
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeMap;
public class MapTest1 {
public static void main(String[] args) {
//创建键盘录入对象
Scanner sc = new Scanner(System.in);

System.out.println("请输入一个纯英语的字符串:");
String s = sc.next();

//创建TreeMap集合对象
TreeMap<Character, Integer> map = new TreeMap<>();

//将字符串转换从字符数组
char[] chars = s.toCharArray();

//遍历字符数组获取每一个字符
for (char c : chars) {
//拿着获取到的字符去集合中键去找,看看有没有这个键
Integer value = map.get(c);

if (value == null) {
map.put(c, 1);
} else {
value++;
map.put(c, value);
}
}

//定义一个StringBuffer作为拼接
StringBuffer sb = new StringBuffer();

//遍历集合得到每一个键和值
Set<Map.Entry<Character, Integer>> entries = map.entrySet();
for (Map.Entry<Character, Integer> entry : entries) {
Character key = entry.getKey();
Integer value = entry.getValue();
sb.append(key).append("(").append(value).append(")");
}

//将StringBuffer转换成字符串输出
String string = sb.toString();
System.out.println("计算每个字符的个数为:" + string);
}
}

七、Collections
针对与集合创建的工具类(最常用的方法,将线程不安全的集合转成线程安全的)

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CollectionsDemo1 {
public static void main(String[] args) {
ArrayList<String> strings = new ArrayList<>();
//转换成线程安全的集合,输出和一些操作都和原本的集合没有区别(相当于包装一下)
//Idea上输入时可以使用Collections.synchronizedList(strings).var快捷键
List<String> strings1 = Collections.synchronizedList(strings);

strings1.add("hello");
strings1.add("world");
strings1.add("java");
strings1.add("bigdata");
strings1.add("hadoop");

System.out.println(strings);
System.out.println(strings1);
}
}

八、集合Collection和Map总结
1、对Collection集合的总结
Collection(接口)的子接口和子接口的一些实现类
-- List(接口) 元素可以重复,有序(存储和取出顺序一致)
--ArrayList
底层数据结构是数组,查询快增删慢
线程不安全的,效率高。
--LinkedList
底层数据结构是链表,查询慢,增删快
线程不安全的,效率高。
--Vector
底层数据结构是数组,查询快,增删慢
线程安全的,效率低(即使是安全的,我们也不用它,后面有更好的集合替代)
-- Set(接口) 元素唯一,无序
--HashSet
底层数据结构是哈希表,元素唯一是由hashCode和equals方法同时保证的
--LinkedHashSet extends HashSet
底层数据结构是哈希表和双链表,保证了元素唯一和有序
--TreeSet
底层数据结构是红黑树,自平衡二叉树
根据构造方法的不同提供两种排序实现方式:
1、无参构造--自然排序(要求数据类型的类要实现Comparable接口,实现compareTo方法)
2、有参构造--参数是实现了Comparator接口并且重写了compare方法的对象
a: 自定义一个类实现
b: 匿名内部类的形式实现

将来开发的时候,我们应该用谁呢?根据以下几点考虑出发
1、元素需要唯一吗?
需要:优先考虑HashSet
不需要:优先考虑ArrayList

2、需要有序吗?
优先考虑ArrayList(sort()方法排序)
如果排序的规则是自定义的,优先考虑TreeSet

如果开发的要求没有那么高也没有上面的要求,就使用ArrayList

2、Map集合总结
Map(接口)元素是由key和value键值对组成,key是唯一的,value是可以重复的
--HashMap
当引用数据类型作为key的时候,该类型必须重写hashCode()和equals()方法,保证唯一
--LinkedHashMap
哈希表保证唯一(键唯一)
链表保证有序(存储和取出顺序一致)
--TreeMap
当引用数据类型作为key的时候,有两种排序方式
自然排序
比较器排序(推荐)

Map常见面试题
HashMap与Hashtable的区别(面试题)
1、HashMap中的key和value允许为null值,而Hashtable不允许(下面举例说明)
2、Hashtable(源代码中的方法基本上都是用synchronized修饰的)是线程安全的,
HashMap是线程不安全的

import java.util.HashMap;
import java.util.Hashtable;
public class HashMapAndHashtableDemo {
public static void main(String[] args) {
HashMap<String, String> map1 = new HashMap<>();
map1.put(null, null);
System.out.println(map1);

Hashtable<String, String> map2 = new Hashtable<>();
//NullPointerException,编译不报错,运行报错
//map2.put(null, null);
System.out.println(map2);
}
}

posted @ 2022-02-13 20:05  等你回眸一笑  阅读(49)  评论(0)    收藏  举报