day06_1【TreeSet集合、Collections】
typora-copy-images-to: img
day06【TreeSet集合、Collections】
今日内容
-
List集合
-
Collections工具类
-
Set集合
教学目标
- 能够说出List集合特点
- 能够使用集合工具类
- 能够使用Comparator比较器进行排序
- 能够使用可变参数
- 能够说出Set集合的特点
- 能够说出哈希表的特点
- 使用HashSet集合存储自定义元素
第一章 TreeSet集合(了解)
1 特点
TreeSet集合是Set接口的一个实现类,底层依赖于TreeMap,是一种基于红黑树的实现,其特点为:
-
元素唯一
-
元素没有索引
-
使用元素的
public TreeSet(): 根据其元素的自然排序进行排序 集合存储的是非自定义类(Integer)大小升序
public TreeSet(Comparator<E> comparator): 根据指定的比较器进行排序 除了集合存储的是非自定义类(Integer)大小升序情况
2 演示
-
TreeSet的排序方式
-
自然排序
package com.itheima.sh.a_treeset_01;
import java.util.TreeSet;
public class TreeSetDemo02 {
public static void main(String[] args) {
//需求:向TreeSet集合中存储非自定义类的对象:String
//1.创建TreeSet集合对象
TreeSet<String> ts = new TreeSet<>();
//2.添加数据
ts.add("abc");
ts.add("def");
ts.add("abcfrg");
ts.add("KAJAHS");
ts.add("KA");
ts.add("zIAUA");
ts.add("Zksjsj");
ts.add("ddff");
ts.add("abc");
//3.输出结果
//ts = [KA, KAJAHS, Zksjsj, abc, abcfrg, ddff, def, zIAUA] 特点:大小升序 数据唯一
/*
1.在java中字符串是通过字符串中的每个字符的编码值进行比较大小的
'0' ---- 48
'A' ---- 65
'a' ---- 97
2. KA < KAJAHS 的原因是:先比较两个字符串的首字母,如果首字母相同在比较第二个字母,如果第二个字母也相同,依次类推
如果一个短的字符串是一个长的字符串的子字符串,那么按照字符串长度比较
*/
System.out.println("ts = " + ts);
}
}
-
比较器排序
自己定义排序方法
public class Demo02_TreeSet {
public static void main(String[] args) {
//创建对象
//使用比较器自己定义排序方法
TreeSet<String> set = new TreeSet<>(new Comparator<String>() {
-
第二章 Collections类
1 Collections常用功能
-
java.utils.Collections
是集合工具类,用来对集合进行操作。常用方法如下:
-
public static void shuffle(List<?> list)
:打乱集合顺序。 -
public static <T> void sort(List<T> list)
:将集合中元素按照默认规则排序(从小到大)。 集合存储的是非自定义类(Integer)大小升序 -
public static <T> void sort(List<T> list,Comparator<? super T> c)
:将集合中元素按照指定规则排序。 除了集合存储的是非自定义类(Integer)大小升序情况 -
代码示例
public class Demo04 {
public static void main(String[] args) {
//Collections是一个工具类,里面的方法都是静态方法
ArrayList<Integer> list = new ArrayList<>();
//添加元素
list.add(123);
list.add(456);
list.add(111);
list.add(10);
list.add(789);
System.out.println("打印集合" + list);
//static void shuffle(List<?> list)
//随机打乱集合元素的顺序
Collections.shuffle(list);
System.out.println("乱序之后" + list);
//static <T> void sort(List<T> list)
//完成集合的排序(从小到大)
Collections.sort(list);
System.out.println("排序之后" + list);
/*
打印集合[123, 456, 111, 10, 789]
乱序之后[10, 789, 111, 456, 123]
排序之后[10, 111, 123, 456, 789]
*/
}
} -
字符串的比较规则
-
字符串是从前往后一个一个比较,如果第一个字符相同,就比较第二个字符,以此类推
-
如果从前往后一个短的字符串是另一个长的字符串的子字符串,就比较长度。例如:"abc" "abcdef"
ArrayList<String> list = new ArrayList<>();
list.add("abc");
list.add("ABC");
list.add("AAA");
list.add("abcd");
//排序
//看一看字符串是怎么排序的?
Collections.sort(list);
/*
字符串是从前往后一个一个比较字符,如果第一个字符相同,就比较第二个字符
如果字符相同就比较长度
*/ // 65 97
System.out.println(list); //[AAA, ABC, abc, abcd]
}
} -
我们的集合按照默认的自然顺序进行了升序排列,如果想要指定顺序那该怎么办呢?
2 Comparator比较器
我们已经使用了集合工具类Collections中带一个参数的排序方法,发现两个参数的排序方法还没有使用,接下来我们学习下带两个参数的排序方法:
public static <T> void sort(List<T> list,Comparator<? super T> )方法灵活的完成,这个里面就涉及到了Comparator这个接口,位于java.util包下,排序是comparator能实现的功能之一,该接口代表一个比较器,比较器具有可比性!顾名思义就是做排序的,通俗地讲需要比较两个对象谁排在前谁排在后,那么比较的方法就是:
public int compare(String o1, String o2):比较其两个参数的顺序。
1.o1 - o2 升序
2.o2 - o1 降序
-
compare方法的底层实现原理解释
说明:该方法要求必须返回一个int类型的整数,然后底层根据返回数据的正负进行比较大小排序。
参数
o1表示后加入的值 (要比较的值)
o2表示已经添加的值(已经比较过的值)
返回值
如果返回值是正数,就会把元素移动到后面(代表o1>o2)
如果返回值是负数,就会把元素移动到前面(代表o1<o2)
如果返回值是0,就表示两个元素相同,就不移动(代表o1=o2) -
排列整数类型
-
需求:对以下数据进行排序
123 456 111 10
-
public class Test03 {
public static void main(String[] args) {
//我如果想要别的排序的方式怎么办?
//要求:想要按照从大到小的顺序排。
//创建集合
ArrayList<Integer> list = new ArrayList<>();
//添加元素
list.add(123);
list.add(456);
list.add(111);
list.add(10);
/*
参数
o1表示后加入的值(要比较的值)
o2表示已经添加的值(已经比较过的值)
返回值
如果返回值是正数,就会把元素移动到后面(代表o1>o2)
如果返回值是负数,就会把元素移动到前面(代表o1<o2)
如果返回值是0,就表示两个元素相同,就不移动(代表o1=o2)
123 456 111 10
o2 o1
升序:o1 - o2
第一次比较:123(o2) 456(o1)---->o1 - o2 大于 0 --->结果:123 456
第二次比较:123 456 111---》
1)456(o2) 111(o1)--》o1 - o2小于0 结果:111 456
2)123(o2) 111(o1) 456---->o1 - o2小于0 结果:111 123
最后结果是:111 123 456
第三次比较:111 123 456 10---》
1)456(o2) 10(o1) --》o1 - o2小于0 结果:10 456
2)123(o2) 10(o1) --》o1 - o2小于0 结果:10 123--->10 123 456
2)111(o2) 10(o1) --》o1 - o2小于0 结果:10 111--->10 111 123 456
降序:o2 - o1
1)123 456 111 10
o2 o1
2)456 123 111 10
o2 o1
3)456 123 111 10
o2 o1
*/
//排序
Collections.sort(list, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
// System.out.println("o1 = " + o1);
// System.out.println("o2 = " + o2);
return o1 - o2;//升序:[10, 111, 123, 456]
// return o2 - o1;//降序:[456, 123, 111, 10]
}
});
System.out.println(list);
}
}
-
排列自定义类型
-
按照年龄从小到大排列
//学生类
public class Student {
String name;
int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
//方便打印
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}package com.itheima.sh.demo_05;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class Test01 {
public static void main(String[] args) {
//测试代码
ArrayList<Student> list = new ArrayList<>();
//添加元素
Student s1 = new Student("石原里美",18);
Student s2 = new Student("柳岩",36);
Student s3 = new Student("新垣结衣",20);
list.add(s1);
list.add(s2);
list.add(s3);
//排序
Collections.sort(list, new Comparator<Student>() {
/*
参数
o1表示后加入的值 (要比较的值)
o2表示已经添加的值(已经比较过的值)
返回值
如果返回值是正数,就会把元素移动到后面 (代表o1>o2)
如果返回值是负数,就会把元素移动到前面 (代表o1<o2)
如果返回值是0,就表示两个元素相同,就不移动 (代表o1=o2)
需求:按照年龄从小到大排列
18 36 20
o2 o1
18 36 20---->18 20 36
o2 o1 o2 o1
*/
@Override
// 18 36 20
//
public int compare(Student o1, Student o2) {
return o1.age - o2.age;
// 相当于36 - 18 结果是一个正数,就会把o1放在后面
// 相当于20 - 36 结果是一个负数,就会把o1放在前面
// 相当于20 - 18 结果是一个正数,就会把o1放在后面
}
});
System.out.println(list);
}
}
-
-
排列自定义类型
-
按照年龄从小到大排列,如果年龄相同,姓名短的在前,姓名长的在后(就是按照名字长度升序排序)
package com.itheima.sh.demo_05;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class Test02 {
public static void main(String[] args) {
//要求:按照年龄从小到大排列,如果年龄相同,姓名短的在前,姓名长的在后
//创建集合
ArrayList<Student> list = new ArrayList<>();
//添加元素
Student s1 = new Student("石原里美",18);
Student s2 = new Student("柳岩",36);
Student s3 = new Student("新垣结衣",20);
Student s4 = new Student("老王",20);
list.add(s1);
list.add(s2);
list.add(s3);
list.add(s4);
/*
参数
o1表示后加入的值 (要比较的值)
o2表示已经添加的值(已经比较过的值)
返回值
如果返回值是正数,就会把元素移动到后面(代表o1>o2)
如果返回值是负数,就会把元素移动到前面(代表o1<o2)
如果返回值是0,就表示两个元素相同,就不移动(代表o1=o2)
要求:按照年龄从小到大排列,如果年龄相同,姓名短的在前,姓名长的在后(就是按照名字长度升序排序)
Student s1 = new Student("石原里美",18);
Student s2 = new Student("柳岩",36);
Student s3 = new Student("新垣结衣",20);
Student s4 = new Student("老王",20);
*/
//排序
Collections.sort(list, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
//先按照年龄排列
if(o1.age != o2.age){
//18 20 36
return o1.age - o2.age;
}
//如果年龄不同,上面就已经返回了结果,程序就不会往下走了
//只有在年龄相同的情况下,程序才会继续往下执行
//年龄相同,再按照姓名长度排序
return o1.name.length() - o2.name.length();
}
});
System.out.println(list);
}
}
-
3 可变参数
在JDK1.5之后,如果我们定义一个方法需要接受多个参数,并且多个参数类型一致,我们可以对其简化.
格式:
修饰符 返回值类型 方法名(参数类型... 形参名){ }
代码演示:
public class ChangeArgs {
public static void main(String[] args) {
//调用
method(10,20); //传入2个整数
method(); //传入了0个整数
method(10,20,30,40,50); //传入了5个整数
int[] arr = {11,22,34};
method(arr); //也可以传入一个数组
}
//要求:想要接受任意个整数
public static void method(int... a){
//可变参数的本质就是一个数组
for (int i = 0; i < a.length; i++) {
System.out.println(a[i]);
}
}
}
注意:
1.一个方法只能有一个可变参数
2.如果方法中有多个参数,可变参数要放到最后。
3.可变参数的本质其实就是一个数组
-
可变参数和数组的区别
可变参数的优势:
传参更方便,可以不传参,可以传递任意个参数,也可以直接传入数组
应用场景: Collections
在Collections中也提供了添加一些元素方法:
public static <T> boolean addAll(Collection<T> c, T... elements)
:往集合中添加一些元素。
代码演示:
public class CollectionsDemo {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<Integer>();
//原来写法
//list.add(12);
//list.add(14);
//list.add(15);
//list.add(1000);
//采用工具类 完成 往集合中添加元素
Collections.addAll(list, 5, 222, 1,2);
System.out.println(list);
}
4 Arrays数组工具类中的asList方法
package com.itheima.sh.c_arrays_03;
import java.util.Arrays;
import java.util.List;
/*
可变参数应用:数组工具类Arrays中的静态方法:
static <T> List<T> asList(T... a) 返回一个受指定数组支持的固定大小的列表。
参数:
a:是一个可变参数,可以接收多个数据或者数组。具体的数据类型由调用的时候确定
返回值:List<T> : 返回的是一个List集合,并且List长度是不能改变的,因为List是由数组转换过来的
*/
public class ArraysDemo01 {
public static void main(String[] args) {
method_3();
}
private static void method_3() {
//需求:将整数数组放到List集合
//1.定义数组
Integer[] arr = {10,20,30};
//2.使用工具类Arrays调用asList方法将上述数组的数据放到List中
List<Integer> list = Arrays.asList(arr);
//输出list
/*
如果想将数组中的基本类型数据放到List集合中,使用Arrays类中的asList方法,那么数组必须是包装类型,不能是基本类型
*/
System.out.println(list.size());//3
System.out.println(list);//[10, 20, 30]
}
private static void method_2() {
//需求:将整数数组放到List集合
//1.定义数组
int[] arr = {10,20,30};
//2.使用工具类Arrays调用asList方法将上述数组的数据放到List中
List<int[]> list = Arrays.asList(arr);
//输出list
/*
由于这里将int基本类型数组arr转换为List集合,所以List泛型是int[]数组类型,那么这里会将数组的地址值放到集合中,并不是数组
中的数据
*/
System.out.println(list.size());//1
System.out.println(list);//[[I@1540e19d]
}
private static void method_1() {
//1.定义数组
String[] arr = {"柳岩","汤唯","柳岩","舒淇"};
//2.使用数组工具类调用asList方法将上述数组转换为List集合
//因为arr数组是String类型,所以List集合的泛型是String类型
List<String> list = Arrays.asList(arr);
//返回的是一个List集合,并且List长度是不能改变的,因为List是由数组转换过来的
//Exception in thread "main" java.lang.UnsupportedOperationException
// list.add("锁哥");
//修改元素内容:把索引是2的位置柳岩变为锁哥
/*
修改后的集合:list = [柳岩, 汤唯, 锁哥, 舒淇]
修改后的数组:数组 = [柳岩, 汤唯, 锁哥, 舒淇]
通过上述结果我们发现修改集合,数组也变,说明内存操作同一个数组空间
*/
list.set(2, "锁哥");
//3.输出集合 [柳岩, 汤唯, 柳岩, 舒淇]
System.out.println("list = " + list);
System.out.println("数组 = " + Arrays.toString(arr));
}
}
小结:
1.如果想将数组中的基本类型数据放到List集合中,使用Arrays类中的asList方法,那么数组必须是包装类型,不能是基本类型