Set集合
LinkHashSet
1.特点: 在HashSet的基础上多了一个有序的特点
Linked 有链表的结构 有序
有序: 存储的顺序 就是 打印顺序
LinkedHashSet<String> set = new LinkedHashSet<>();
set.add("v");
set.add("m");
set.add("a");
set.add("b");
set.add("c");
set.add("d");
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) {
String string = (String) iterator.next();
System.out.println(string);
}
输出结果:
v
m
a
b
c
d
利用Set集合特性, 去重List集合
// 利用Set集合
// 去除ArrayList集合中的重复元素(操作原ArrayList)
// ArrayList 保存a a, b b, c c, d d
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("a");
list.add("b");
list.add("b");
list.add("c");
list.add("c");
list.add("d");
list.add("d");
// 1.创建set集合 去重
LinkedHashSet<String> set = new LinkedHashSet<>();
// 2.利用set集合 addAll list集合元素 ,达到去重目的
set.addAll(list);
// 3.清空list集合
list.clear();
// 4.再将Set集合元素还给list集合
list.addAll(set);
System.out.println(list);
TreeSet
1.TreeSet特点: 无序 无下标 不重复
特有功能: 排序
// 举例: TreeSet的去重和排序
// 创建TreeSet 保存4个数字 查看打印结果
TreeSet<Integer> set = new TreeSet<>();
set.add(11);
set.add(22);
set.add(44);
set.add(33);
set.add(22);
System.out.println(set);
输出结果:
[11,22,33,44]
TreeSet的排序原理
1️⃣
(泛型是自定义类: 先让自定义类实现Comparable接口,再重写compareTo方法)
2️⃣
(泛型是系统类时: 重新定义一个类实现Comparator比较器接口,重写compare方法;
注意: 在声明这个集合时,要将重新自定义的类对象 添加到集合TreeSet的构造方法中)
// 举例 : 自定义类 在TreeSet集合中的排序
自定义类在TreeSet排序顺序
1.实现Comparable接口;
2.实现接口中的方法;
3.编写你的排序规则(重写CompareTo方法)
// 自定义类
class Person implements Comparable<Person>{
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
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 "Person [name=" + name + ", age=" + age + "]";
}
/*
* 实现接口中的比较方法compareTo()
* 返回 0 只有一个元素(不存储)
* 正数 按正序(正的存储顺序)输出
* 负数 按倒序(倒的存储顺序)输出
*
* TreeSet
* 二叉树排序
* 存规则
* 1.比我小的数 放我的左边(返回负数时效果)
* 2.比我大的数 放我的右边(返回正数时效果)
* 3.不存(返回0)
* 取规则
* 从小到大 升序输出
*/
@Override
public int compareTo(Person o) {
// 重新编写 比较的规则
// 按年龄比较 this 和 传入的参数
// 主要按年龄,次要按姓名(年龄相同,就比较姓名)
int num1 = this.getAge() - o.getAge();
if (num1 == 0) {
int num2 = this.getName().compareTo(o.getName());
return num2;
}else {
// 将返回值 赋值不等于0,可使集合不去重,并按升序排序
return 1;
}
// 将 自定义类对象 传入TreeSet集合中
// TreeSet保存4个人
Person person1 = new Person("1",11);
Person person2 = new Person("2",22);
Person person3 = new Person("3",33);
Person person4 = new Person("4",44);
TreeSet<Person> set = new TreeSet<>();
set.add(person1);
set.add(person2);
set.add(person3);
set.add(person4);
System.out.println(set);
// 举例 : 系统类(不能重写系统类中的方法) 在TreeSet方法中的排序
系统类在TreeSet排序顺序
1.自定义类实现Comparator 比较器 接口
2.自定类中可以编写比较规则
3.将比较的规则实现类对象 直接传入到 TreeSet构造方法当中
// 系统类更改比较规则 按字符串长度
// TreeSet保存四个字符串
// 按字符串长度排序
// 自定义类
class CompareLength implements Comparator<String>{
@Override
public int compare(String o1, String o2) {
// TODO Auto-generated method stub
int num = o1.length() - o2.length();
int rel = num == 0 ? o1.compareTo(o2) : num;
return rel == 0 ? 1 : rel;// 不让删除相同的字符串.强行返回1
}
}
// 将自定义类传入 TreeSet集合中
TreeSet<String> set = new TreeSet<>(new CompareLength());
/*第三步:将比较的规则实现类对象 直接传入到 TreeSet构造方法当中*/
set.add("1111");
set.add("33");
set.add("4");
set.add("222");
System.out.println(set);
输出结果:
[4,33,222,1111]
// TreeSet集合 不去重排序练习 (用来熟悉步骤)
// 练习1.
// 在一个集合ArrayList
// 中存储了无序并且重复的字符串
// 要求 排序,而且还不能去除重复(用比较器)
// 主要按字符串长度比较 次要按字符串比
ArrayList<String> list = new ArrayList<>();
list.add("wanglong");
list.add("dong");
list.add("liu");
list.add("wangjun");
list.add("dong");
TreeSet<String> set = new TreeSet<>(new CompareLength());
set.addAll(list);
System.out.println(set);
输出结果:
[liu, dong, dong, wangjun, wanglong]
// 练习2
// 键盘接收一个字符串,
// 程序对其中所有字符进行排序 要求保留重复的
class CompareChar implements Comparator<Character>{
@Override
public int compare(Character o1, Character o2) {
int num = o1.compareTo(o2);// 或者 o1 - o2
return num == 0 ? 1 : num;
}
}
System.out.println("请输入一个字符串: ");
Scanner scanner = new Scanner(System.in);
String string = scanner.nextLine();
TreeSet<Character> list = new TreeSet<>(new CompareChar());
for (int i = 0; i < string.length(); i++) {
list.add(string.charAt(i));
}
System.out.println(list);
// 练习3
// 程序启动后, 可以从键盘输入接收多个整数,
// 直到输入quit时结束输入.
// 把所有输入的整数降序排列打印
class CompareInt implements Comparator<Integer>{
@Override
public int compare(Integer o1, Integer o2) {
int num = - (o1 - o2);
return num == 0 ? 1 : num;
}
}
TreeSet<Integer> set = new TreeSet<>(new CompareInt());
System.out.println("请输入一个整数(quit结束): ");
Scanner scanner = new Scanner(System.in);
while (true) {
// 接受用户输入
String string = scanner.nextLine();
// 判断是否停止
if (string.equals("quit")) {
break;
}
// 字符串转数字
int num = Integer.parseInt(string);
// 添加到集合
set.add(num);
}
System.out.println(set);
双列集合Map
1.双列集合
Map(双列集合的父接口)
特点: 1️⃣以 键值对的形式 来存储数据 key(键值)---value(值)
2️⃣键值是唯一的 (键值不能重复,输入 重复键值 会覆盖原有的value值)
HashMap与HashSet有关系吗?
有关系,HashSet 依赖 HashMap
实际上 向HashSet中添加元素 相当于 向map中添加元素,只不过设置value=null
2.双列集合的建立 put(key,value)
// Map的创建
HashMap<String,Integer> map = new HashMap<>();
// 添加键值对元素
// put方法返回值是 该键被覆盖的value值
Integer v1 = map.put("张三", 23);
Integer v2 = map.put("李四", 20);
Integer v3 = map.put("王五", 21);
Integer v4 = map.put("赵六", 22);
Integer v5 = map.put("张三", 2018);
System.out.println(map);
System.out.println(v1);
System.out.println(v2);
System.out.println(v3);
System.out.println(v4);
System.out.println(v5);
输出结果:
{张三=20, 李四=22, 王五=2018, 赵六=21}
null
null
null
null
23
3.双列集合的方法
/*
* map 方法
* 包含 key
* 包含 value
* 获取所有key的Set集合
* 获取所有value集合
* 通过key删除整个键值对
* 清空map
*/
HashMap<String,Integer> map = new HashMap<>();
map.put("明明", 23);
map.put("东东", 20);
map.put("生生", 21);
map.put("柳柳", 22);
// 判断map中是否包含 key或value
boolean b1 = map.containsKey("明明");
boolean b2 = map.containsValue(15);
System.out.println(b1);
System.out.println(b2);
// 获取所有key的Set集合(核心方法) keySet()
Set<String> set = map.keySet();
System.out.println(set);
// 获取所有value集合 values()
Collection<Integer> set1 = map.values();
System.out.println(set1);
// 通过key删除整个键值对 会返回value值
Integer a = map.remove("明明");
System.out.println(a);
// 清空map
map.clear();
System.out.println(map);
// 通过key值寻找value值
Integer c = map.get("明明");
4.双列集合的遍历-迭代器 或 Entry对象(键值对)
// 通过迭代器遍历
HashMap<Person, String> map = new HashMap<>();
map.put(new Person("明明", 23), "安徽");
map.put(new Person("东东", 15), "上海");
map.put(new Person("生生", 45), "广东");
map.put(new Person("柳柳", 34), "江西");
// 首先取出所有key的集合
Set<Person> keyset = map.keySet();
// 取出集合中的迭代器
Iterator<Person> iterator = keyset.iterator();
while (iterator.hasNext()) {
// 遍历所有key
Person key = (Person) iterator.next();
// 利用key取出对应value
String value = map.get(key);
System.out.println("key = " + key + " value = " + value);
}
// 利用Entry对象来遍历map entrySet()
// Entry对象中封装了 一个键值对 对象
// 一个key 一个对应的value
HashMap<String, Integer> map = new HashMap<>();
map.put("明明", 23);
map.put("东东", 15);
map.put("生生", 45);
map.put("柳柳", 34);
// 获取所有Entry对象的Set集合
Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
// 取出迭代器
Iterator< Map.Entry<String, Integer>> a = entrySet.iterator();
// 遍历所有entry对象
while (a.hasNext()) {
// 取出每一个entry对象
Map.Entry<String, Integer> entry = (Map.Entry<String, Integer>) a.next();
// 打印
System.out.println("key = " + entry.getKey() + " value = " + entry.getValue());
}
5.HashMap和LinkedHashMap的对比
HashMap 无序
LinkedHashMap 有序(存储顺序)
附加:Collections的工具类
集合的工具类 Collections(静态方法)
// 随机顺序(洗牌方法)
Collections.shuffle(集合对象);
// 排序方法
// 排 自定义对象类型行不行?
// 需要实现comparable接口或比较器
Collections.sort(集合对象);
// 二分查找 没有这个值,返回 -(该存索引 + 1)
int index = Collections.binarySearch(集合对象, 查找对象);
// 集合反转
Collections.reverse(集合对象);