1.Collections
1.1可变参数
就是一种特殊形参,定义在方法、构造器的形参列表里
定义格式是:方法名(数据类型... 形参名称){ }
注意:
可变参数在方法内部就是一个数组
一个形参列表中可变参数只能有一个
可变参数必须放在形参列表的最后面
public class Demo {
public static void main(String[] args) {
//计算2个整数的和
add(2,3);
//计算3个整数的和
add(3,4,5);
//计算4个整数的和
add(4,5,6);
//计算n个整数的和
add(4,5,6,7,8,9,10,22);
}
public static void add(int...num){
int sum = 0;
for (int i : num) {
sum += i;
}
System.out.println(sum);
}
}
1.2Collections
是一个用来操作集合的工具类
常用方法 static <T> boolean addAll(单列集合,可变参数) 批量添加元素 static void shuffle(List集合) 打乱List集合元素顺序,每次调用都会打乱 static <T> void sort(List集合) List集合进行自然排序 static <T> void sort(List集合,比较器) List集合进行比较器排序
public class Demo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
//static <T> boolean addAll(单列集合,可变参数) 批量添加元素
Collections.addAll(list, "a", "b", "c", "d", "e");
System.out.println(list);
//static void shuffle(List集合) 打乱List集合元素顺序,每次调用都会打乱
Collections.shuffle(list);
System.out.println(list);
//static <T> void sort(List集合) List集合进行自然排序
List<Integer> num = new ArrayList<>();
Collections.addAll(num, 44,22,11,33,55 );
Collections.sort(num);
System.out.println(num);
//排自定义类对象,需要指定排序规则
List<Student> stuList = new ArrayList<>();
stuList.add(new Student("zhangsan", 18));
stuList.add(new Student("wangwu", 22));
stuList.add(new Student("zhaoliu", 21));
stuList.add(new Student("lisi", 19));
stuList.add(new Student("qianqi", 20));
//static<T> void sort(List集合,比较器);List集合进行比较器排序
Collections.sort(stuList, ( o1, o2)-> o1.getAge() - o2.getAge());
System.out.println(stuList);
}
}
2.Map集合
Map集合称为双列集合,一次需要存一对数据做为一个元素, 格式:{key1=value1 , key2=value2 , key3=value3 , ...}
Map集合的每个元素分为两部分:key和value,key称为键,value称为值,整体叫键值对,因此Map也叫“键值对集合”
Map集合的所有键是不允许重复的,但值可以重复,键和值是一一对应的,每一个键只能找到自己对应的值
Map应用场景:需要存储一一对应的数据时,就可以考虑使用Map集合来做
2.1Map集合体系
Map集合体系的特点:
Map系列集合的特点都是由键决定的,值只是一个附属品,值是不做要求的
HashMap: 无序、不重复 (用的最多)
LinkedHashMap :有序、不重复
TreeMap: 按照大小默认升序排序、不重复
2.2Map的常用方法
双列集合根接口,它的功能是全部双列集合都可以继承过来使用的。
V put(K key,V value) 添加元素 int size() 获取集合的大小 boolean isEmpty() 判断集合是否为空,为空返回true, 反之 V get(Object key) 根据键获取对应值 V remove(Object key) 根据键删除整个元素 boolean containsKey(Object key) 判断是否包含某个键 boolean containsValue(Object value) 判断是否包含某个值 Set<K> keySet() 获取全部键的集合 Collection<V> values() 获取Map集合的全部值 void clear() 清空集合
public class Demo1 {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
//V put(K key,V value) 添加元素
map.put("001", "张三");
map.put("002", "李四");
map.put("003", "王五");
map.put("004", "赵六");
System.out.println(map);
//int size() 获取集合的大小
System.out.println(map.size()); //4
//boolean isEmpty() 判断集合是否为空,为空返回true, 反之
System.out.println(map.isEmpty()); //false
//V get(Object key) 根据键获取对应值
String value = map.get("001");
System.out.println(value); //张三
//V remove(Object key) 根据键删除整个元素
map.remove("001");
System.out.println(map);
//boolean containsKey(Object key) 判断是否包含某个键
System.out.println(map.containsKey("001")); //false
//boolean containsValue(Object value) 判断是否包含某个值
System.out.println(map.containsValue("李四")); //true
//Set<K> keySet() 获取全部键的集合
Set<String> strings = map.keySet();
System.out.println(strings); //002,003,004
//Collection<V> values() 获取Map集合的全部值
Collection<String> values = map.values();
System.out.println(values); //李四,王五,赵六
//void clear() 清空集合
map.clear();
System.out.println(map); //{}
}
}
2.3遍历方式
Map集合的遍历方式一:先获取Map集合全部的键,再通过遍历键来找值
public class Demo2 {
public static void main(String[] args) {
//1. 创建map
Map<String, String> map = new HashMap<>();
map.put("a", "aaa");
map.put("b", "bbb");
map.put("c", "ccc");
System.out.println(map);
//2. 各种方式进行遍历
test1(map);
test2(map);
test3(map);
}
//遍历方式1: 先获取Map集合全部的键,再通过遍历键来找值
private static void test1(Map<String, String> map) {
Set<String> keys = map.keySet();
for (String key : keys) {
String string = map.get(key);
System.out.println(key + "=" + string);
}
}
Map集合的遍历方式二:把“键值对”看成一个整体进行遍历
//遍历方式2: 将map中的所有键值对放入一个set集合中, 然后遍历set集合拿到每个键值对, 再取里面的键值
private static void test2(Map<String, String> map) {
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key + "=" + value);
}
}
Map集合的遍历方式三 :结合lambda的遍历方法
//遍历方式3: Lambda, 使用foreach(BiConsumer bc)
private static void test3(Map<String, String> map) {
map.forEach((k,v)->System.out.println(k+"="+v));
}
}
2.4HashMap
HashMap跟HashSet的底层原理是一模一样的,都是基于哈希表实现的。
实际上:Set系列集合的底层就是基于Map实现的,只是Set集合中的元素只要键数据,不要值数据而已。
JDK8之前,哈希表 = 数组+链表
JDK8开始,哈希表 = 数组+链表+红黑树
哈希表是一种增删改查数据,性能都较好的数据结构。
HashMap的键依赖hashCode方法和equals方法保证键的唯一
2.5LinkedHashMap
底层数据结构依然是基于哈希表实现的,只是每个键值对元素又额外的多了一个双链表的机制记录元素顺序(保证有序)。
实际上:原来学习的LinkedHashSet集合的底层原理就是LinkedHashMap。
2.6TreeMap
特点:不重复、无索引、可排序(按照键的大小默认升序排序,只能对键排序)
原理:TreeMap跟TreeSet集合的底层原理是一样的,都是基于红黑树实现的排序。
TreeMap集合同样也支持两种方式来指定排序规则
让类实现Comparable接口,重写比较规则。
TreeMap集合有一个有参数构造器,支持创建Comparator比较器对象,以便用来指定比较规则。
Map集合案例-省和市
要求:
在程序中记住如下省份和其对应的城市信息,记录成功后,要求可以查询出湖北省的城市信息。
public class Demo7 {
public static void main(String[] args) {
Map<String, ArrayList> map = new HashMap<>();
ArrayList<String> list1 = new ArrayList<>();
Collections.addAll(list1,"南京市","扬州市","苏州市","无锡市","常州市");
map.put("江苏省",list1);
ArrayList<String> list2 = new ArrayList<>();
Collections.addAll(list2,"武汉市","孝感市","十堰市","宜昌市","鄂州市");
map.put("湖北省",list2);
ArrayList<String> list3 = new ArrayList<>();
Collections.addAll(list3,"石家庄市","唐山市","邢台市","保定市","张家口市");
map.put("河北省",list3);
Scanner sc = new Scanner(System.in);
System.out.println("请输入你要查询的城市:");
String city = sc.next();
Set<Map.Entry<String, ArrayList>> entries = map.entrySet();
for (Map.Entry<String, ArrayList> entry : entries) {
if (entry.getKey().equals(city)){
ArrayList value = entry.getValue();
System.out.println(value);
break;
}else {
}
}
}
}
3.Stream
Stream也叫Stream流,是Jdk8开始新增的一套API ,可以用于操作集合或者数组的数据。
优势: Stream流大量的结合了Lambda的语法风格来编程,提供了一种更加强大,更加简单的方式
操作集合或者数组中的数据,代码更简洁,可读性更好。
3.1Stream的使用步骤
1. 先得到集合或者数组的Stream流(获取)
2.调用Stream流的方法对数据进行处理(操作)
3.获取处理的结果(终结)
3.2Stream的常用的方法
中间方法 对stream流进行操作的方法, 他们调用完成后会返回新的Stream流,可以继续使用(支持链式编程)。
常见的中间方法 Stream<T> filter(Predicate<? super T> p) 按照规则过滤,保留满足条件的元素 Stream<T> sorted() 升序排序 Stream<T> sorted(Comparator<? super T> c) 按照规则排序 Stream<T> limit(long maxSize) 截取 Stream<T> skip(long n) 跳过 Stream<R> map(Function<? super T, extends R> mapper) 对元素进行加工,并返回对应的新流 Stream<T> distinct() 去重 static <T> Stream<T> concat(Stream a,Stream b) 合并流
public class Demo3 {
public static void main(String[] args) {
List<Integer> list = List.of(61, 57, 66, 77, 88, 44, 100, 89, 97, 47, 70);
//需求1: 找出所有及格的分数,并打印
System.out.println("=================");
list.stream()
.filter(e -> e >= 60)
.forEach(System.out::println);
//需求2: 找出所有及格的分数, 正序排列, 打印输出
System.out.println("=================");
list.stream()
.filter(e -> e > 60)
.sorted()
.forEach(System.out::println);
//需求3: 找出所有及格的分数, 倒序排列, 打印输出
System.out.println("=================");
list.stream()
.filter(e -> e > 60)
.sorted((o1, o2) -> o2 - o1)
.forEach(System.out::println);
//需求4: 找出所有及格的分数, 倒序排列, 取前3名, 打印输出
System.out.println("=================");
list.stream()
.filter(e -> e > 60)
.sorted((o1, o2) -> o2 - o1)
.limit(3)
.forEach(System.out::println);
//需求5: 找出所有及格的分数, 倒序排列, 取前4-6名, 打印输出
System.out.println("=================");
list.stream()
.filter(e -> e > 60)
.sorted((o1, o2) -> o2 - o1)
.skip(3)
.limit(3)
.forEach(System.out::println);
//需求6: 找出所有及格的分数, 倒序排列, 取前4-6名, 将每个人的分数加10分, 打印输出
System.out.println("=================");
list.stream()
.filter(e -> e > 60)
.sorted((o1, o2) -> o2 - o1)
.skip(3)
.limit(3)
.map(e->e + 10)
.forEach(System.out::println);
}
}
终结方法1
调用完成后,不会返回新Stream了,没法继续使用流了。
它的作用是对流中的数据进行筛选(遍历、最大、最小、统计个数)
常用方法
void forEach(Consumer consumer) 遍历流中的数据
long count() 统计流中元素的个数
Optional max(Comparator<? super T> comparator) 获取流中的最大值
Optional min(Comparator<?super T> comparator) 获取流中的最小值
public class Demo4 {
public static void main(String[] args) {
List<Student> list = List.of(
new Student("玄奘", 60, 165.5),
new Student("悟空", 50, 175.5),
new Student("悟能", 55, 145.5),
new Student("悟净", 40, 185.5)
);
//1. 打印出集合中所有元素
list.stream()
.forEach(e ->System.out.println(e));
//2. 统计出身高不足170的人数
long count = list.stream()
.filter(e -> e.getHeight() < 170)
.count();
System.out.println(count);
//3. 请找出年龄最大的对象, 并输出(了解)
Optional<Student> max = list.stream()
.max((o1, o2) -> o1.getAge() > o2.getAge() ? 1 : -1);
System.out.println("年龄最大的对象:"+max);
//4. 请找出身高最高的对象, 并输出(了解)
Optional<Student> max1 = list.stream()
.max((o1, o2) -> o1.getHeight() > o2.getHeight() ? 1 : -1);
System.out.println("身高最高的对象:"+max1);
}
}
class Student {
private String name;
private int age;
private double height;
public Student() {
}
public Student(String name, int age, double height) {
this.name = name;
this.age = age;
this.height = height;
}
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;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", height=" + height +
'}';
}
}
终结方法2
调用完成后,不会返回新Stream了,没法继续使用流了。
它的作用是用来收集Stream流的结果转回到集合或者数组中去返回。
常见方法
R collect(Collector collector); 将流中数据收集到指定集合,参数传递Collectors工具类调用对应方法
Collectors.toList()
Collectors.toSet()
Collectors.toMap()
Object[] toArray();
public class Demo5 {
public static void main(String[] args) {
List<Teacher> list = List.of(
new Teacher("玄奘", 60, 165.5),
new Teacher("悟空", 50, 175.5),
new Teacher("悟空", 50, 175.5),
new Teacher("悟能", 55, 145.5),
new Teacher("悟净", 40, 185.5));
//1. 请找出身高超过170的教师, 并放到一个新数组中
Object[] array = list.stream()
.filter(e -> e.getHeight() > 170)
.toArray();
System.out.println(Arrays.toString(array));
//2. 请找出身高超过170的教师, 并放到一个新List集合中
List<Teacher> list1 = list.stream()
.filter(e -> e.getHeight() > 170)
.collect(Collectors.toList());
System.out.println(list1);
//3. 请找出身高超过170的教师, 并放到一个新Set集合中
Set<Teacher> collect = list.stream()
.filter(e -> e.getHeight() > 170)
.collect(Collectors.toSet());
System.out.println(collect);
//4. 请找出所有的教师的姓名和身高, 放到一个新Map集合中
Map<Object, Object> collect1 = list.stream().distinct()
.collect(Collectors.toMap((Teacher teacher) -> teacher.getName(),
(Teacher teacher) -> teacher.getHeight()));
System.out.println(collect1);
}
}
class Teacher {
private String name;
private int age;
private double height;
public Teacher() {
}
public Teacher(String name, int age, double height) {
this.name = name;
this.age = age;
this.height = height;
}
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;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Teacher teacher = (Teacher) o;
return age == teacher.age && Double.compare(teacher.height, height) == 0 && Objects.equals(name, teacher.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age, height);
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", age=" + age +
", height=" + height +
'}';
}
}