Day27
反射案例
案例一:万能数组扩容
注意:copyOf、toString
public class Test01 { /** * 知识点:反射案例 之 万能数组扩容 * * 注意:copyOf、toString */ public static void main(String[] args) { String[] ss = {"aaa","bbb","ccc"}; String[] copyOf = MyArrays.copyOf(ss, 5); System.out.println(MyArrays.toString(copyOf)); } }
MyArrays内:
public static <T> T[] copyOf(T[] arr,int newLength){ int copyLen = Array.getLength(arr); if(copyLen > newLength){ copyLen = newLength; } //arr -- String[].class Class<? extends Object[]> clazz = arr.getClass(); //elementType -- String.class Class<?> componentType = clazz.getComponentType(); @SuppressWarnings("unchecked") T[] ts = (T[]) Array.newInstance(componentType, newLength); for (int i = 0; i < copyLen; i++) { Object element = Array.get(arr, i); Array.set(ts, i, element); } return ts; } public static String toString(Object[] arr){ String str = "["; for (Object element : arr) { if(str.length() != 1){ str += ","; } str += element; } str += "]"; return str; } }
注意:1.copyOf方法使用了泛型 T[],而泛型只适用于引用数据类型,所以此时的copyOf方法是无法传入基本数据类型的数组的,要解决这个问题,应该在下面进行基本数据类型的方法重载。
2.方法重载应该选择挨个地对基本数据类型进行重写,而不是用object类型,原因在于Java 泛型的擦除机制。这个机制是指在编译时,泛型类型信息会被擦除,这意味着在生成的字节码中,泛型类型的信息将被替换为原始类型(或者对象类型)。所以会报错,报错信息为这个方法和上面那个泛型的方法完全一样,因为T泛型进行擦除后就是Object类。
案例二:业务与逻辑分离的思想
需求:让用户选择不同获取数据的方式
public static void main(String[] args) { Scanner scan = new Scanner(System.in); showMenu(); int num = scan.nextInt(); DataSourse dataSourse = getBean(num); dataSourse.getDataSourse(); scan.close(); } public static DataSourse getBean(int num){ DataSourse[] beans = DataCenter.getBean(); return beans[num-1]; } public static void showMenu(){ String[] menus = DataCenter.getMenus(); System.out.println("请选择以下获取数据的方式:"); for (String string : menus) { System.out.println(string); } }
public abstract class DataSourse { public abstract void getDataSourse(); } public class LocalDataSourse extends DataSourse{ @Override public void getDataSourse() { System.out.println("获取本地数据"); BufferedReader br = null; try { br = new BufferedReader(new FileReader("hhy.txt")); char[] cs = new char[1024]; int len; while((len = br.read(cs)) != -1){ System.out.println(new String(cs, 0, len)); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if(br != null){ try { br.close(); } catch (IOException e) { e.printStackTrace(); } } } } } //获取网络数据的类 public class NetworkDataSource extends DataSourse{ @Override public void getDataSourse() { System.out.println("获取网络数据"); try { URL url = new URL("https://suggest.taobao.com/sug?code=gbk&q=始祖鸟&callback=cb"); //获取链接对象 HttpURLConnection connection = (HttpURLConnection) url.openConnection(); //设置参数 connection.setConnectTimeout(5000);//设置连接超时时间 connection.setReadTimeout(5000);//设置读取超时时间 connection.setDoInput(true);//设置允许使用输入流 connection.setDoOutput(true);//设置允许使用输出流 //获取响应状态码 int responseCode = connection.getResponseCode(); if(responseCode == HttpURLConnection.HTTP_OK){ //获取响应中的数据 BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(),"UTF-8")); char[] cs = new char[1024]; int len; while((len = br.read(cs)) != -1){ System.out.println(new String(cs, 0, len)); } br.close(); }else if(responseCode == HttpURLConnection.HTTP_NOT_FOUND){ System.out.println("响应错误,页面未找到"); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } public class OtherDataSourse extends DataSourse{ @Override public void getDataSourse() { System.out.println("获取其他资源"); } }
//从配置文件中读取配置信息,并将这些配置信息用于初始化两个静态列表 public class DataCenter { private static ArrayList<String> menuList; private static ArrayList<DataSourse> beanList; static{ menuList = new ArrayList<>(); Properties p = new Properties(); try { p.load(DataSourse.class.getClassLoader().getResourceAsStream("MenuConfig.properties")); } catch (IOException e) { e.printStackTrace(); } String menu = p.getProperty("menu"); String[] split = menu.split(","); for (String string : split) { menuList.add(string); } } public static String[] getMenus(){ String[] menus = new String[menuList.size()]; menuList.toArray(menus); return menus; } static{ beanList = new ArrayList<>(); Properties p = new Properties(); try { p.load(DataSourse.class.getClassLoader().getResourceAsStream("BeanConfig.properties")); } catch (IOException e) { e.printStackTrace(); } String path = p.getProperty("path"); String[] split = path.split(","); for (String string : split) { try { Class<?> clazz = Class.forName(string); DataSourse dataSourse = (DataSourse) clazz.newInstance(); beanList.add(dataSourse); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } } public static DataSourse[] getBean(){ DataSourse[] beans = new DataSourse[beanList.size()]; beanList.toArray(beans); return beans; } }
案例三:获取注解信息
public class Test01 { /** * 知识点:反射案例 之 获取注解信息 */ public static void main(String[] args) { Student stu = new Student("侯小康", '男', 23, "2402", "001"); String insertSql = ReflexUtil.getInsertSql(stu); System.out.println(insertSql); //insert into s_student(s_name,s_sex,s_age,s_class_id,s_id) values('侯小康','男',23,'2402','001'); } }
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface FieldInfo { String name(); String type(); int length(); } @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface TableInfo { String value(); }
@TableInfo("s_student") public class Student { @FieldInfo(name="s_name",type="varchar",length=255) private String name; @FieldInfo(name="s_sex",type="varchar",length=255) private char sex; @FieldInfo(name="s_age",type="int",length=255) private int age; @FieldInfo(name="s_class_id",type="varchar",length=255) private String classId; @FieldInfo(name="s_id",type="varchar",length=255) private String id; public Student() { } public Student(String name, char sex, int age, String classId, String id) { this.name = name; this.sex = sex; this.age = age; this.classId = classId; this.id = id; } public String getName() { return name; } public char getSex() { return sex; } public int getAge() { return age; } public String getClassId() { return classId; } public String getId() { return id; } public void setName(String name) { this.name = name; } public void setSex(char sex) { this.sex = sex; } public void setAge(int age) { this.age = age; } public void setClassId(String classId) { this.classId = classId; } public void setId(String id) { this.id = id; } }
ReflexUtil工具类中:
public static String getInsertSql(Object obj){ Class<? extends Object> clazz = obj.getClass(); //获取表名 -- 获取类上的注解信息 TableInfo tableInfo = clazz.getAnnotation(TableInfo.class); String tableName = tableInfo.value(); //获取字段名和字段数据 -- 获取属性上的注解信息 Field[] fields = clazz.getDeclaredFields(); StringBuffer fieldNameSB = new StringBuffer(); StringBuffer valueSB = new StringBuffer(); for (Field field : fields) { field.setAccessible(true); //获取属性上的注解信息(字段名和字段类型) FieldInfo fieldInfo = field.getAnnotation(FieldInfo.class); String name = fieldInfo.name(); String type = fieldInfo.type(); Object value = null; try { value = field.get(obj); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } if(fieldNameSB.length() != 0){ fieldNameSB.append(","); } fieldNameSB.append(name); if(valueSB.length() != 0){ valueSB.append(","); } if(type.equals("varchar")){ valueSB.append("'"); } valueSB.append(value); if(type.equals("varchar")){ valueSB.append("'"); } } String insertSql = "insert into " + tableName + "(" + fieldNameSB.toString() + ") values(" + valueSB.toString() + ");"; return insertSql; }
JDK1.8新特性简介
- 速度更快 - 优化底层源码,比如HashMap、ConcurrentHashMap
- 代码更少 - 添加新的语法Lambda表达式
- 强大的Stream API
- 便于并行
- 最大化减少空指针异常 - Optional
Lambda表达式
简介
Lambda是一个匿名函数(方法), 允许把函数作为一个方法的参数 。利用Lambda表达式可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。一般都是优化匿名内部类
基础语法
无参数、无返回值的抽象方法
public class Test1 {
@Test
public void test01() {
// I1 i1 = new I1() {
// @Override
// public void method() {
// System.out.println("传统使用匿名内部类的方式");
// }
// };
// i1.method();
I1 i1 = ()-> System.out.println("采用Lambda表达式的方式");
i1.method();
}
}
interface I1{
public void method();//无参数、无返回值的抽象方法
}
一个参数、无返回值的抽象方法
public class Test1 {
@Test
public void test01() {
I1 i1 = (x)-> System.out.println("采用Lambda表达式的方式 " + x);
i1.method(1000);
}
}
interface I1{
public void method(int num1);//一个参数、无返回值的抽象方法
}
多个参数、无返回值的抽象方法
public class Test1 {
@Test
public void test01() {
I1 i1 = (x,y,z)->
System.out.println("采用Lambda表达式的方式 " + x + y + z);
i1.method(1000,2000,3000);
}
}
interface I1{
//多个参数、无返回值的抽象方法
public void method(int num1,int num2,int num3);
}
多个参数、有返回值的抽象方法
public class Test1 {
@Test
public void test01() {
I1 i1 = (x,y,z)-> x+y+z;
int result = i1.method(1000,2000,3000);
System.out.println(result);
}
}
interface I1{
//多个参数、有返回值的抽象方法
public int method(int num1,int num2,int num3);
}
注意点
- 重写方法的形参只有一个时,可以不加小括号
- Lambda表达式当中不允许声明一个与局部变量同名的参数或者局部变量
- Lambda表达式中访问外层的局部变量,外层的局部变量自动变成隐式常量,默认添加final
- 重写方法的形参同时加类型或同时不加类型
public class Test1 {
@Test
public void test01() {
int x;
int num = 10;
I1 i1 = x -> System.out.println(x + (num++));
i1.method(1000);
I2 i2 = (int x,int y) -> {
int result = x+y;
return result;
};
int result = i2.method(10, 20);
System.out.println(result);
}
}
interface I1{
public void method(int num1);
}
interface I2{
public int method(int num1,int num2);
}
练习
- 调用Collections.sort()方法,通过定制排序比较两个Student对象(先按年龄比较,年龄相同按照薪资比较),使用Lambda表达式作为参数传递
public class Test1 {
@Test
public void test01() {
List<Student> stuList = Arrays.asList(
new Student("张三", 28, 4800,Course.JAVA),new Student("李四", 36, 7200,Course.JAVA),new Student("王五", 19, 9600,Course.HTML),new Student("赵六", 42, 6100,Course.HTML),new Student("孙七", 23, 9600,Course.PYTHON),new Student("吴八", 31, 3000,Course.PYTHON));
Collections.sort(stuList, (a,b)-> {
if(a.getAge() == b.getAge()){
return Double.compare(a.getSalary(),b.getSalary());
}
return a.getAge()-b.getAge();
});
for (Student stu : stuList) {
System.out.println(stu);
}
}
}
enum Course{//课程枚举
JAVA,HTML,PYTHON;
}
class Student{//学生类
private String name;
private int age;
private double salary;
private Course course;
...
}
- 创建I1接口,创建抽象方法:public String getValue(String str),在测试类中编写方法使用接口作为参数,将一个字符串转为大写,并作为方法的返回值
public class Test1 {
@Test
public void test01() {
String strHandler = strHandler("abc", x-> x.toUpperCase());
System.out.println(strHandler);
}
public static String strHandler(String str,I1 i1){
return i1.getValue(str);
}
}
interface I1{
public String getValue(String str);
}
- 创建I1<T,R>接口,泛型T为参数,R为返回值,创建抽象方法:public R add(T t1,T t2),在测试类中编写方法使用接口作为参数,计算两个long类型的和
public class Test1 {
@Test
public void test01() {
Long addLong = addLong(100L, 200L, (x,y)-> x+y);
System.out.println(addLong);
}
public static Long addLong(Long l1,Long l2,I1<Long,Long> i1){
return i1.add(l1, l2);
}
}
interface I1<T,R>{
public R add(T t1,T t2);
}
函数式接口
简介
函数式接口是指仅仅只包含一个抽象方法的接口,jdk1.8提供了一个@FunctionalInterface注解来定义函数式接口,如果我们定义的接口不符合函数式的规范便会报错。配合Lambda表达式一起使用
四大核心函数式接口
函数式接口 | 参数类型 | 返回类型 | 用途 |
---|---|---|---|
Consumer 消费型接口 | T | void | void accept(T t); |
Supplier 供给型接口 | void | T | T get(); |
Function<T, R> 函数型接口 | T | R | R apply(T t); |
Predicate 断言型接口 | T | boolean | booelan test(T t); |
BiConsumer<T, U> | T,U | void | 对类型为T,U参数应用操作。包含方法为void accept(T t,U u); |
BiFunction<T, U, R> | T,U | R | 对类型为T,U参数应用操作,并返回R类型的结果。包含方法为R apply(T t,U u); |
UnaryOperator extends Function<T, T> | T | T | 对类型为T的对象进行一元运算,并返回T类型的结果。包含方法为T apply(T t); |
BinaryOperator extends BiFunction<T,T,T> | T,T | T | 对类型为T的对象进行二元运算,并返回T类型的结果。包含方法为T apply(T t1,T t2); |
ToIntFunction ToLongFunction ToDoubleFunction | T | int long double | 分别计算int、long、double值的函数 |
IntFunction LongFunction DoubleFunction | int long double | R | 参数为int、long、double类型的函数 |
应用场景
当我们编写一个接口,这个接口只有一个抽象方法时,就可以使用函数式接口去替代
public static void main(String[] args) { String method = method("abc", (str)->str.toUpperCase()); System.out.println(method); } public static String method(String str,Function<String, String> fun){ return fun.apply(str); }
方法、构造方法和数组引用
方法、构造方法和数组引用就是Lamdba的另一种表现形式
方法引用
若Lamdba表达式中的内容由方法已经实现了,可以使用方法引用这个技能
当你需要使用方法引用时,目标引用放在分隔符::前,方法的名称放在后面
对象::实例方法
Lambda表达式中调用方法的参数类型和返回值必须和函数式接口中的抽象方法一致
public class Test1 {
@Test
public void test01() {
// I1 i1 = (x)->System.out.println(x);
// i1.method("abcd");
//println里的参数列表和返回值类型必须和method方法一致才行
PrintStream ps = System.out;
I1 i1 = ps::println;//对象::实例方法
i1.method("abcd");
}
}
interface I1{
public void method(String str);
}
类名::静态方法
Lambda表达式中调用方法的参数类型和返回值必须和函数式接口中的抽象方法一致
public class Test1 {
@Test
public void test01() {
// Comparator<Integer> com = (x,y)-> Integer.compare(x, y);
// int compare = com.compare(10, 20);
// System.out.println(compare);
//类名::静态方法
Comparator<Integer> com = Integer::compare;
int compare = com.compare(10, 20);
System.out.println(compare);
}
}
类名::实例方法
Lambda表达式参数列表中第一个参数必须是实例方法的调用者
Lambda表达式参数列表中第二个参数必须是实例方法的参数
public class Test1 {
@Test
public void test01() {
// I1<String> i1 = (x,y) -> x.equals(y);
// boolean method = i1.method("abc", "abc");
// System.out.println(method);
//类名::实例方法
//注意:Lambda表达式参数列表中第一个参数是equals方法的调用者,
// Lambda表达式参数列表中第二个参数是equals方法的参数
I1<String> i1 = String::equals;
boolean method = i1.method("abc", "abc");
System.out.println(method);
}
}
interface I1<T>{
public boolean method(T t1,T t2);
}
构造方法引用
类名::new
需要调用的构造方法的参数列表必须和函数式接口中抽象方法的参数列表一致
public class Test04 {
/**
* 知识点:构造方法的引用
*/
public static void main(String[] args) {
//调用Student类的无参构造去创建对象
I3 i3 = Student::new;
Student stu1 = i3.method();
System.out.println(stu1);
//调用Student类的有参构造去创建对象
I4 i4 = Student::new;
Student stu2 = i4.method("小康", 23, 12000, Course.JAVA);
System.out.println(stu2);
}
}
interface I3{
public Student method();
}
interface I4{
public Student method(String name, int age, double salary, Course course);
}
数组引用
语法格式:type[]::new
public class Test1 {
@Test
public void test01() {
//创建数组
I1<String[]> i1 = String[]::new;
System.out.println(Arrays.toString(i1.method(10)));
}
}
interface I1<T>{
public T method(int capacity);
}
Stream
Stream(流)是数据渠道,用于操作数据源(集合、数组等),生成元素序列。换言之,集合是存储数据的容器,流使用操作这些数据的
Stream可以对集合进行非常复杂的查找、过滤、映射数据等操作,类似于SQL执行数据库查询。Stream提供了一种高效且易于使用的处理数据的方式
注意:
- Stream不会存储数据
- Stream不会改变源数据,通过一系列操作数据源会返回一个持有结果的新Stream
- Stream操作是延迟执行的,意味着流会等到需要结果的时候才执行
执行步骤
- 创建Stream:通过数据源(集合、数组等)获取一个Stream
- 中间操作:中间操作链,对源数据的数据进行处理
- 终止操作:执行中间操作,并产生结果
创建Stream
public class Test01 { /** * 知识点:获取Stream流对象 */ @Test public void test01(){ //方式一:通过集合获取流对象 List<Student> stuList = Arrays.asList( new Student("张三", 28, 4800,Course.JAVA), new Student("李四", 36, 7200,Course.JAVA), new Student("王五", 19, 9600,Course.HTML), new Student("赵六", 42, 6100,Course.HTML), new Student("孙七", 23, 9600,Course.PYTHON), new Student("吴八", 31, 3000,Course.PYTHON), new Student("李四", 36, 7200,Course.JAVA)); // Stream<Student> stream = stuList.stream(); // stream.forEach(new Consumer<Student>() { // @Override // public void accept(Student t) { // System.out.println(t); // } // }); stuList.stream().forEach(System.out::println); } @Test public void test02(){ //方式二:通过数组获取Stream流对象 String[] names = {"aaa","bbb","ccc","ddd","eee"}; // Stream<String> stream = Arrays.stream(names); // stream.forEach(System.out::println); Arrays.stream(names).forEach(System.out::println); } @Test public void test03(){ //方式三:通过Stream的静态方法of()获取流对象 Stream<String> stream = Stream.of("aaa","bbb","ccc","ddd","eee"); stream.forEach(System.out::println); } @Test public void test04(){ //方式四:创建无限流、迭代流 Stream<Integer> stream = Stream.iterate(10, (x)->x+100); Stream<Integer> newStram = stream.limit(5); newStram.forEach(System.out::println); } @Test public void test05(){ //方式四:创建无限流 Stream<Double> stream = Stream.generate(Math::random); Stream<Double> newStram = stream.limit(5); newStram.forEach(System.out::println); } }
中间操作 - 筛选与切片
public class Test02 { /** * 知识点:中间操作 - 筛选与切片 */ List<Student> stuList = Arrays.asList( new Student("张三", 28, 4800,Course.JAVA), new Student("李四", 36, 7200,Course.JAVA), new Student("王五", 19, 9600,Course.HTML), new Student("赵六", 42, 6100,Course.HTML), new Student("孙七", 23, 9600,Course.PYTHON), new Student("吴八", 31, 3000,Course.PYTHON), new Student("李四", 36, 7200,Course.JAVA)); @Test public void test01(){ //需求1:过滤掉工资小于5000的学生对象 stuList.stream().filter((stu)->{ double salary = stu.getSalary(); if(salary>5000){ return true; } return false; }).forEach(System.out::println); } @Test public void test02(){ //需求2:过滤掉工资小于5000的学生对象,并显示3条 // stuList.stream().filter((stu)->{ // double salary = stu.getSalary(); // if(salary>5000){ // return true; // } // return false; // }).limit(3).forEach(System.out::println); stuList.stream().filter((stu)->{return stu.getSalary()>5000;}).limit(3).forEach(System.out::println); } @Test public void test03(){ //需求3:过滤掉工资小于5000的学生对象,并跳过第1个学生对象 // stuList.stream().filter((stu)->{ // double salary = stu.getSalary(); // if(salary>5000){ // return true; // } // return false; // }).skip(1).forEach(System.out::println); stuList.stream().filter((stu)->{return stu.getSalary()<5000;}).skip(1).forEach(System.out::println); } @Test public void test04(){ //需求4:过滤掉工资小于5000的学生对象,并筛选掉重复元素 // stuList.stream().filter((stu)->{ // double salary = stu.getSalary(); // if(salary>5000){ // return true; // } // return false; // }).distinct().forEach(System.out::println); stuList.stream().filter((stu)->stu.getSalary()<5000).distinct().forEach(System.out::println); } }
中间操作 - 映射
public class Test03 { /** * 知识点:中间操作 - 映射 */ List<Student> stuList = Arrays.asList( new Student("张三", 28, 4800,Course.JAVA), new Student("李四", 36, 7200,Course.JAVA), new Student("王五", 19, 9600,Course.HTML), new Student("赵六", 42, 6100,Course.HTML), new Student("孙七", 23, 9600,Course.PYTHON), new Student("吴八", 31, 3000,Course.PYTHON), new Student("李四", 36, 7200,Course.JAVA)); @Test public void test01(){ //获取所有学生的姓名 //Stream 类的 map 函数用于将流中的每个元素转换为另一种形式 // stuList.stream().map(new Function<Student, String>() { // @Override // public String apply(Student stu) { // return stu.getName(); // } // }).forEach(new Consumer<String>() { // @Override // public void accept(String name) { // System.out.println(name); // } // }); // stuList.stream().map((stu)->stu.getName()).forEach(System.out::println); stuList.stream().map(Student::getName).forEach(System.out::println); } }
中间操作 - 排序
public class Test04 { /** * 知识点:中间操作 - 排序 */ List<Student> stuList = Arrays.asList( new Student("张三", 28, 4800,Course.JAVA), new Student("李四", 36, 7200,Course.JAVA), new Student("王五", 19, 9600,Course.HTML), new Student("赵六", 42, 6100,Course.HTML), new Student("孙七", 23, 9600,Course.PYTHON), new Student("吴八", 31, 3000,Course.PYTHON), new Student("李四", 36, 7200,Course.JAVA)); @Test public void test01(){ //使用元素原有排序规则(Comparable<T>) //需求:按照年龄排序 stuList.stream().sorted().forEach(System.out::println); } @Test public void test02(){ //使用自定义排序规则(Comparator<T>) //需求:按照工资排序 stuList.stream().sorted((stu1,stu2)->{return Double.compare(stu1.getSalary(), stu2.getSalary());}).forEach(System.out::println); } }
终止操作 - 匹配与查找
public class Test1 { List<Student> stuList = Arrays.asList( new Student("张三", 28, 4800,Course.JAVA), new Student("李四", 36, 7200,Course.JAVA), new Student("王五", 19, 9600,Course.HTML), new Student("赵六", 42, 6100,Course.HTML), new Student("孙七", 23, 9600,Course.PYTHON), new Student("吴八", 31, 3000,Course.PYTHON), new Student("吴八", 31, 3000,Course.PYTHON)); @Test public void test01() { //需求1:检查流中所有元素是否匹配 工资>5000 boolean allMatch = stuList.stream().allMatch((stu) -> stu.getSalary()>5000); System.out.println(allMatch);//false //需求2:检查流中所有元素至少匹配一个 工资>5000 boolean anyMatch = stuList.stream().anyMatch((stu) -> stu.getSalary()>5000); System.out.println(anyMatch);//true //需求3:检查流中所有元素是否没有匹配 工资>5000 boolean noneMatch = stuList.stream().noneMatch((stu) -> stu.getSalary()>5000); System.out.println(noneMatch); //需求4:返回工资最高的学生信息 Optional<Student> findFirst = stuList.stream(). sorted((stu1,stu2)->Double.compare( stu1.getSalary(),stu2.getSalary())). findFirst(); Student stu = findFirst.get(); //这种写法防止NullPointerException出现 //Student stu = findFirst.orElse(new Student()); System.out.println(stu); //需求5:返回随机学生信息(但效果不好) Optional<Student> findAny = stuList.stream().findAny(); Student stu = findAny.get(); System.out.println(stu); //需求6:获取学生个数 long count = stuList.stream().count(); System.out.println(count); //需求7:获取最高工资的学生信息 Optional<Student> max = stuList.stream(). max((stu1,stu2)->Double.compare(stu1.getSalary(),stu2.getSalary())); System.out.println(max.get()); //需求8:获取最低工资的学生信息 Optional<Student> min = stuList.stream(). min((stu1,stu2)->Double.compare(stu1.getSalary(),stu2.getSalary())); System.out.println(min.get()); } } enum Course{//课程枚举 JAVA,HTML,PYTHON; } class Student implements Comparable<Student>{//学生类 private String name; private int age; private double salary; private Course course; ... }
终止操作 - 归约
public class Test1 { List<Integer> numList = Arrays.asList(1,2,3,4,5,6,7,8,9,10); List<Student> stuList = Arrays.asList( new Student("张三", 28, 4800,Course.JAVA), new Student("李四", 36, 7200,Course.JAVA), new Student("王五", 19, 9600,Course.HTML), new Student("赵六", 42, 6100,Course.HTML), new Student("孙七", 23, 9600,Course.PYTHON), new Student("吴八", 31, 3000,Course.PYTHON), new Student("李四", 36, 7200,Course.JAVA)); @Test public void test01() { //需求:获取numList集合中元素的总和 Integer reduce = numList.stream(). reduce(0, (x,y)->x+y); System.out.println(reduce); } @Test public void test02() { //需求:获取stuList集合中所有学生工资总和 Optional<Double> reduce = stuList.stream(). map(Student::getSalary).reduce(Double::sum); Double sumSalary = reduce.get(); System.out.println(sumSalary); } } enum Course{//课程枚举 JAVA,HTML,PYTHON; } class Student implements Comparable<Student>{//学生类 private String name; private int age; private double salary; private Course course;
终止操作 - 收集
public class Test1 { List<Student> stuList = Arrays.asList( new Student("张三", 28, 4800,Course.JAVA), new Student("李四", 36, 7200,Course.JAVA), new Student("王五", 19, 9600,Course.HTML), new Student("赵六", 42, 6100,Course.HTML), new Student("孙七", 23, 9600,Course.PYTHON), new Student("吴八", 31, 3000,Course.PYTHON), new Student("李四", 36, 7200,Course.JAVA)); @Test public void test01() { //把数据收集到集合中 //需求1:把当前学生姓名提取出来,并把数据放入List集合中 List<String> list = stuList.stream(). map(Student::getName). collect(Collectors.toList()); list.forEach(System.out::println); //需求2:把当前学生姓名提取出来,并把数据放入Set集合中 Set<String> set = stuList.stream(). map(Student::getName).collect(Collectors.toSet()); set.forEach(System.out::println); //需求3:把当前学生姓名提取出来,并把数据放入指定集合中 HashSet<String> hashSet = stuList.stream(). map(Student::getName).collect(Collectors.toCollection(HashSet::new)); hashSet.forEach(System.out::println); } @Test public void test02() { //收集流中的各种数据 //需求1:收集/获取学生个数 Long count = stuList.stream(). map(Student::getName).collect(Collectors.counting()); System.out.println(count); //需求2:收集/获取学生平均工资 Double avg = stuList.stream(). collect(Collectors.averagingDouble(Student::getSalary)); System.out.println(avg); //需求3:收集/获取学生总工资 Double sum = stuList.stream(). collect(Collectors.summingDouble(Student::getSalary)); System.out.println(sum); //需求4:收集/获取学生工资最大值 Optional<Double> max = stuList.stream().map(Student::getSalary). collect(Collectors.maxBy(Double::compareTo)); System.out.println(max.get()); //需求5:收集/获取学生工资最小值 Optional<Double> min = stuList.stream().map(Student::getSalary). collect(Collectors.minBy(Double::compareTo)); System.out.println(min.get()); //需求6:收集/获取工资最多的学生信息 Optional<Student> maxStu = stuList.stream(). collect(Collectors.maxBy( (stu1,stu2)-> (int)(stu1.getSalary()-stu2.getSalary()))); System.out.println(maxStu.get()); //需求7:收集/获取工资最少的学生信息 Optional<Student> minStu = stuList.stream(). collect(Collectors.minBy( (stu1,stu2)-> (int)(stu1.getSalary()-stu2.getSalary()))); System.out.println(minStu.get()); } @Test public void test03() {//分组 //需求:按照学科分组 Map<Course, List<Student>> map = stuList.stream().collect( Collectors.groupingBy(Student::getCourse)); System.out.println(map); } @Test public void test04() {//多级分组 //需求:按照学科分组,在按照年龄分组 Map<Course, Map<String, List<Student>>> map = stuList.stream(). collect(Collectors.groupingBy( Student::getCourse,Collectors.groupingBy((stu)->{ if(((Student)stu).getAge() < 28){ return "青年"; }else if(((Student)stu).getAge() < 40){ return "中年"; }else{ return "老年"; } }))); System.out.println(map); } @Test public void test05() {//分区 //需求:按照工资5000为标准分区 Map<Boolean, List<Student>> map = stuList.stream().collect( Collectors.partitioningBy((stu) -> stu.getSalary()>5000)); System.out.println(map); } @Test public void test06() {//获取元素中字段的各种信息 //需求:获取学生工资信息,再获取总值、平均值、最大值、最小值 DoubleSummaryStatistics collect = stuList.stream().collect( Collectors.summarizingDouble(Student::getSalary)); System.out.println(collect.getSum()); System.out.println(collect.getAverage()); System.out.println(collect.getMax()); System.out.println(collect.getMin()); } @Test public void test07() {//拼接信息 //需求:拼接学生姓名 String str1 = stuList.stream().map(Student::getName).collect( Collectors.joining()); System.out.println(str1); String str2 = stuList.stream().map(Student::getName).collect( Collectors.joining(",")); System.out.println(str2); String str3 = stuList.stream().map(Student::getName).collect( Collectors.joining(",","--","--")); System.out.println(str3); } } enum Course{//课程枚举 JAVA,HTML,PYTHON; } class Student implements Comparable<Student>{//学生类 private String name; private int age; private double salary; private Course course; ... }
…