Java:Arrays类、Lambda表达式、JDK新特性(方法引用) --黑马笔记

一、Arrays类

1.1 Arrays基本使用

Arrays是操作数组的工具类,它可以很方便的对数组中的元素进行遍历、拷贝、排序等操作。

下面我们用代码来演示一下:遍历、拷贝、排序等操作。需要用到的方法如下:

public class ArraysTest1 {public static void main(String[] args) {// 1、public static String toString(类型[] arr): 返回数组的内容int[] arr = {10, 20, 30, 40, 50, 60};System.out.println(Arrays.toString(arr));//[10, 20, 30, 40, 50, 60]// 2、public static 类型[] copyOfRange(类型[] arr, 起始索引, 结束索引) :拷贝数组(指定范围,包前不包后)int[] arr2 = Arrays.copyOfRange(arr, 1, 4);System.out.println(Arrays.toString(arr2));//[20, 30, 40]// 3、public static copyOf(类型[] arr, int newLength):拷贝数组,可以指定新数组的长度。int[] arr3 = Arrays.copyOf(arr, 10);System.out.println(Arrays.toString(arr3));//[10, 20, 30, 40, 50, 60, 0, 0, 0, 0]// 4、public static setAll(double[] array, IntToDoubleFunction generator):把数组中的原数据改为新数据又存进去。double[] prices = {99.8, 128, 100};//                  0     1    2// 把所有的价格都打八折,然后又存进去。Arrays.setAll(prices, new IntToDoubleFunction() {@Overridepublic double applyAsDouble(int value) {// value = 0  1  2return prices[value] * 0.8;}});System.out.println(Arrays.toString(prices));//[79.84, 102.4, 80.0]// 5、public static void sort(类型[] arr):对数组进行排序(默认是升序排序)Arrays.sort(prices);System.out.println(Arrays.toString(prices));//[79.84, 80.0, 102.4]}
}

1.2 Arrays操作对象数组

刚才我们使用Arrays操作数组时,数组中存储存储的元素是int类型、double类型,是可以直接排序的,而且默认是升序排列。

如果数组中存储的元素类型是自定义的对象,如何排序呢?接下来,我们就学习一下Arrays如何对对象数组进行排序。

首先我们要准备一个Student类,代码如下:

public class Student implements Comparable<Student>{private String name;private double height;private int age;public Student(String name, double height, int age) {this.name = name;this.height = height;this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", height=" + height +", age=" + age +'}';}
}

如果再写一个测试类,往数组中存储4个学生对象。此时,运行代码你会发现是会报错的。

因为Arrays根本就不知道按照什么规则进行排序。为了让Arrays知道按照什么规则排序,我们有如下的两种办法。

排序方式1:让Student类实现Comparable接口,同时重写compareTo方法。Arrays的sort方法底层会根据compareTo方法的返回值是正数、负数、还是0来确定谁大、谁小、谁相等。

代码如下:

public class Student implements Comparable<Student>{private String name;private double height;private int age;//...get、set、空参数构造方法、有参数构造方法...自己补全// 指定比较规则// this  o@Overridepublic int compareTo(Student o) {// 约定1:认为左边对象 大于 右边对象 请您返回正整数// 约定2:认为左边对象 小于 右边对象 请您返回负整数// 约定3:认为左边对象 等于 右边对象 请您一定返回0/* if(this.age > o.age){return 1;}else if(this.age < o.age){return -1;}return 0;*///上面的if语句,也可以简化为下面的一行代码return this.age - o.age; // 按照年龄升序排列// return o.age - this.age; // 按照年龄降序排列}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", height=" + height +", age=" + age +'}';}
}

排序方式2:在调用Arrays.sort(数组,Comparator比较器);时,除了传递数组之外,传递一个Comparator比较器对象。Arrays的sort方法底层会根据Comparator比较器对象的compare方法方法的返回值是正数、负数、还是0来确定谁大、谁小、谁相等。

代码如下:

public class ArraysTest2 {public static void main(String[] args) {// 目标:掌握如何对数组中的对象进行排序。Student[] students = new Student[4];students[0] = new Student("蜘蛛精", 169.5, 23);students[1] = new Student("紫霞", 163.8, 26);students[2] = new Student("紫霞", 163.8, 26);students[3] = new Student("至尊宝", 167.5, 24);// 2、public static <T> void sort(T[] arr, Comparator<? super T> c)// 参数一:需要排序的数组// 参数二:Comparator比较器对象(用来制定对象的比较规则)Arrays.sort(students, new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {// 制定比较规则了:左边对象 o1   右边对象 o2// 约定1:认为左边对象 大于 右边对象 请您返回正整数// 约定2:认为左边对象 小于 右边对象 请您返回负整数// 约定3:认为左边对象 等于 右边对象 请您一定返回0
//                if(o1.getHeight() > o2.getHeight()){
//                    return 1;
//                }else if(o1.getHeight() < o2.getHeight()){
//                    return -1;
//                }
//                return 0; // 升序return Double.compare(o1.getHeight(), o2.getHeight()); // 升序// return Double.compare(o2.getHeight(), o1.getHeight()); // 降序}});System.out.println(Arrays.toString(students));}
}

二、Lambda表达式

我们学习一个JDK8新增的一种语法形式,叫做Lambda表达式。作用:用于简化匿名内部类代码的书写。

2.1 Lambda表达式基本使用

怎么去简化呢?Lamdba是有特有的格式的,按照下面的格式来编写Lamdba。

(被重写方法的形参列表) -> {
    被重写方法的方法体代码;
}

 要给说明一下的是,在使用Lambda表达式之前,必须先有一个接口,而且接口中只能有一个抽象方法。(注意:不能是抽象类,只能是接口)

像这样的接口,我们称之为函数式接口,只有基于函数式接口的匿名内部类才能被Lambda表达式简化。

public interface Swimming{void swim();
}

有了以上的Swimming接口之后,接下来才能再演示,使用Lambda表达式,简化匿名内部类书写。

public class LambdaTest1 {public static void main(String[] args) {// 目标:认识Lambda表达式.//1.创建一个Swimming接口的匿名内部类对象Swimming s = new Swimming(){@Overridepublic void swim() {System.out.println("学生快乐的游泳~~~~");}};s.swim();//2.使用Lambda表达式对Swimming接口的匿名内部类进行简化Swimming s1 = () -> {System.out.println("学生快乐的游泳~~~~");};s1.swim();}
}

好的,我们现在已经知道Lamdba表达式可以简化基于函数式接口的匿名内部类的书写。接下来,我们可以把刚才使用Arrays方法时的代码,使用Lambda表达式简化一下了。

public class LambdaTest2 {public static void main(String[] args) {// 目标:使用Lambda简化函数式接口。double[] prices = {99.8, 128, 100};//1.把所有元素*0.8: 先用匿名内部类写法Arrays.setAll(prices, new IntToDoubleFunction() {@Overridepublic double applyAsDouble(int value) {// value = 0  1  2return prices[value] * 0.8;}});//2.把所有元素*0.8: 改用Lamdba表达式写法Arrays.setAll(prices, (int value) -> {return prices[value] * 0.8;});System.out.println(Arrays.toString(prices));System.out.println("-----------------------------------------------");Student[] students = new Student[4];students[0] = new Student("蜘蛛精", 169.5, 23);students[1] = new Student("紫霞", 163.8, 26);students[2] = new Student("紫霞", 163.8, 26);students[3] = new Student("至尊宝", 167.5, 24);//3.对数组中的元素按照年龄升序排列: 先用匿名内部类写法Arrays.sort(students, new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {return Double.compare(o1.getHeight(), o2.getHeight()); // 升序}});//4.对数组中的元素按照年龄升序排列: 改用Lambda写法Arrays.sort(students, (Student o1, Student o2) -> {return Double.compare(o1.getHeight(), o2.getHeight()); // 升序});System.out.println(Arrays.toString(students));}
}

2.2 Lambda表达式省略规则

刚才我们学习了Lambda表达式的基本使用。Java觉得代码还不够简单,于是还提供了Lamdba表达式的几种简化写法。具体的简化规则如下:

1.Lambda的标准格式
    (参数类型1 参数名1, 参数类型2 参数名2)->{
        ...方法体的代码...
        return 返回值;
    }

2.在标准格式的基础上()中的参数类型可以直接省略
    (参数名1, 参数名2)->{
        ...方法体的代码...
        return 返回值;
    }
    
3.如果{}总的语句只有一条语句,则{}可以省略、return关键字、以及最后的“;”都可以省略
    (参数名1, 参数名2)-> 结果
    
4.如果()里面只有一个参数,则()可以省略
    参数名->结果

接下来从匿名内部类开始、到Lambda标准格式、再到Lambda简化格式,一步一步来简化一下。同学们体会一下简化的过程。

public class LambdaTest2 {public static void main(String[] args) {// 目标:使用Lambda简化函数式接口。double[] prices = {99.8, 128, 100};//1.对数组中的每一个元素*0.8: 匿名内部类写法Arrays.setAll(prices, new IntToDoubleFunction() {@Overridepublic double applyAsDouble(int value) {// value = 0  1  2return prices[value] * 0.8;}});//2.需求:对数组中的每一个元素*0.8,使用Lambda表达式标准写法Arrays.setAll(prices, (int value) -> {return prices[value] * 0.8;});//3.使用Lambda表达式简化格式1——省略参数类型Arrays.setAll(prices, (value) -> {return prices[value] * 0.8;});//4.使用Lambda表达式简化格式2——省略()Arrays.setAll(prices, value -> {return prices[value] * 0.8;});//5.使用Lambda表达式简化格式3——省略{}Arrays.setAll(prices, value -> prices[value] * 0.8 );System.out.println(Arrays.toString(prices));System.out.println("------------------------------------Student[] students = new Student[4];students[0] = new Student("蜘蛛精", 169.5, 23);students[1] = new Student("紫霞", 163.8, 26);students[2] = new Student("紫霞", 163.8, 26);students[3] = new Student("至尊宝", 167.5, 24);//1.使用匿名内部类Arrays.sort(students, new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {return Double.compare(o1.getHeight(), o2.getHeight()); // 升序}});//2.使用Lambda表达式表达式——标准格式Arrays.sort(students, (Student o1, Student o2) -> {return Double.compare(o1.getHeight(), o2.getHeight()); // 升序});//3.使用Lambda表达式表达式——省略参数类型Arrays.sort(students, ( o1,  o2) -> {return Double.compare(o1.getHeight(), o2.getHeight()); // 升序});//4.使用Lambda表达式表达式——省略{}Arrays.sort(students, ( o1,  o2) -> Double.compare(o1.getHeight(), o2.getHeight()));System.out.println(Arrays.toString(students));}
}

三、JDK8新特性(方法引用)

我们知道Lambda是用来简化匿名代码的书写格式的,而方法引用是用来进一步简化Lambda表达式的,它简化的更加过分。

3.1 静态方法引用

我们先学习静态方法的引用,还是用之前Arrays代码来做演示。现在准备好下面的代码:

public class Test1 {public static void main(String[] args) {Student[] students = new Student[4];students[0] = new Student("蜘蛛精", 169.5, 23);students[1] = new Student("紫霞", 163.8, 26);students[2] = new Student("紫霞", 163.8, 26);students[3] = new Student("至尊宝", 167.5, 24);// 原始写法:对数组中的学生对象,按照年龄升序排序Arrays.sort(students, new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {return o1.getAge() - o2.getAge(); // 按照年龄升序排序}});// 使用Lambda简化后的形式Arrays.sort(students, (o1, o2) -> o1.getAge() - o2.getAge());}
}

现在,我想要把下图中Lambda表达式的方法体,用一个静态方法代替:

准备另外一个类CompareByData类,用于封装Lambda表达式的方法体代码;

public class CompareByData {public static int compareByAge(Student o1, Student o2){return o1.getAge() - o2.getAge(); // 升序排序的规则}
}

现在我们就可以把Lambda表达式的方法体代码,改为下面的样子:

Arrays.sort(students, (o1, o2) -> CompareByData.compareByAge(o1, o2));

Java为了简化上面Lambda表达式的写法,利用方法引用可以改进为下面的样子。实际上就是用类名调用方法,但是把参数给省略了。这就是静态方法引用:

//静态方法引用:类名::方法名
Arrays.sort(students, CompareByData::compareByAge);

3.2 实例方法引用

还是基于上面的案例,我们现在来学习一下实例方法的引用。现在,我想要把下图中Lambda表达式的方法体,用一个实例方法代替。

在CompareByData类中,再添加一个实例方法,用于封装Lambda表达式的方法体。

接下来,我们把Lambda表达式的方法体,改用对象调用方法:

CompareByData compare = new CompareByData();
Arrays.sort(students, (o1, o2) -> compare.compareByAgeDesc(o1, o2)); // 降序

最后,再将Lambda表达式的方法体,直接改成方法引用写法。实际上就是用类名调用方法,但是省略的参数。这就是实例方法引用:

CompareByData compare = new CompareByData();
Arrays.sort(students, compare::compareByAgeDesc); // 降序

3.2 特定类型的方法引用

在学习之前还是需要给大家说明一下,这种特定类型的方法引用是没有什么道理的,只是语法的一种约定,遇到这种场景,就可以这样用。

Java约定:
    如果某个Lambda表达式里只是调用一个实例方法,并且前面参数列表中的第一个参数作为方法的主调,后面的所有参数都是作为该实例方法的入参时,则就可以使用特定类型的方法引用。
格式:
    类型::方法名

 

public class Test2 {public static void main(String[] args) {String[] names = {"boby", "angela", "Andy" ,"dlei", "caocao", "Babo", "jack", "Cici"};// 要求忽略首字符大小写进行排序。Arrays.sort(names, new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {// 制定比较规则。o1 = "Andy"  o2 = "angela"return o1.compareToIgnoreCase(o2);}});//lambda表达式写法Arrays.sort(names, ( o1,  o2) -> o1.compareToIgnoreCase(o2) );//特定类型的方法引用!Arrays.sort(names, String::compareToIgnoreCase);System.out.println(Arrays.toString(names));}
}

3.3 构造器引用

还是先说明一下,构造器引用在实际开发中应用的并不多,目前还没有找到构造器的应用场景。所以大家在学习的时候,也只是关注语法就可以了。

现在,我们准备一个JavaBean类,Car类:

public class Car {private String name;private double price;public Car() {}public Car(String name, double price) {this.name = name;this.price = price;}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}@Overridepublic String toString() {return "Car{" +"name='" + name + '\'' +", price=" + price +'}';}
}

因为方法引用是基于Lamdba表达式简化的,所以也要按照Lamdba表达式的使用前提来用,需要一个函数式接口,接口中代码的返回值类型是Car类型。

interface CreateCar{Car create(String name, double price);
}

最后,再准备一个测试类,在测试类中创建CreateCar接口的实现类对象,先用匿名内部类创建、再用Lambda表达式创建,最后改用方法引用创建。同学们只关注格式就可以,不要去想为什么(语法就是这么设计的)。

public class Test3 {public static void main(String[] args) {// 1、创建这个接口的匿名内部类对象。CreateCar cc1 = new CreateCar(){@Overridepublic Car create(String name, double price) {return new Car(name, price);}};//2、使用匿名内部类改进CreateCar cc2 = (name,  price) -> new Car(name, price);//3、使用方法引用改进:构造器引用CreateCar cc3 = Car::new;//注意:以上是创建CreateCar接口实现类对象的几种形式而已,语法一步一步简化。//4、对象调用方法Car car = cc3.create("奔驰", 49.9);System.out.println(car);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2779321.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

【机器学习】数据清洗之识别异常点

&#x1f388;个人主页&#xff1a;甜美的江 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;机器学习 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进步…

IDEA中Git的使用小技巧-Toolbar(工具栏)的设置

目录 1 前言 2 步骤 2.1 打开设置 2.2 找到Menus and Toolbars 2.3 Menus and Toolbars界面的介绍 2.4 选择工具 2.5 查看 1 前言 工具栏的合理运用&#xff0c;能够极大程度上为我们省时省力 &#xff0c;接下来我将以Git工具的添加&#xff0c;介绍如何定制我们IDEA…

C++学习笔记 | 基于Qt框架开发实时成绩显示排序系统1

目标&#xff1a;旨在开发一个用户友好的软件工具&#xff0c;用于协助用户基于输入对象的成绩数据进行排序。该工具的特色在于&#xff0c;新输入的数据将以红色高亮显示&#xff0c;从而直观地展现出排序过程中数据变化的每一个步骤。 结果展示&#xff1a; 本程序是一个基于…

游戏服务器哪家强?国内几款主流云服务器测评

游戏服务器租用多少钱一年&#xff1f;1个月游戏服务器费用多少&#xff1f;阿里云游戏服务器26元1个月、腾讯云游戏服务器32元&#xff0c;华为云26元&#xff0c;游戏服务器配置从4核16G、4核32G、8核32G、16核64G等配置可选&#xff0c;游戏专业服务器公网带宽10M、12M、15M…

决策树之scikit-learn

实例 from sklearn.datasets import load_iris from sklearn import tree import matplotlib.pyplot as plt# Load iris dataset iris load_iris() X, y iris.data, iris.target# Fit the classifier clf tree.DecisionTreeClassifier() clf clf.fit(X, y)# Plot the deci…

python 基础知识点(蓝桥杯python科目个人复习计划37)

今日复习内容&#xff1a;DFS--回溯 1.介绍 回溯&#xff1a;就是DFS是一种&#xff0c;在搜索尝试过程中寻找问题的解&#xff0c;当发现已不满足求解条件时&#xff0c;就“回溯”返回&#xff0c;尝试别的路径。 回溯更强调&#xff1a;此路不通&#xff0c;另寻他路&…

linux系统下vscode portable版本的c++/Cmake环境搭建001

linux系统下vscode portable版本的Cmake环境搭建 vscode portable 安装安装基本工具安装 build-essential安装 CMake final script code安装插件CMake Tools & cmakeC/C Extension Pack Testsettings,jsonCMakeLists.txt调试和运行工具 CG 目的&#xff1a;希望在获得一个新…

自定义Function MyRandom函数获得随机数

《VBA信息获取与处理》教程(版权10178984)是我推出第六套教程&#xff0c;目前已经是第一版修订了。这套教程定位于最高级&#xff0c;是学完初级&#xff0c;中级后的教程。这部教程给大家讲解的内容有&#xff1a;跨应用程序信息获得、随机信息的利用、电子邮件的发送、VBA互…

手把手教你开发Python桌面应用-PyQt6图书管理系统-图书信息表格数据显示及搜索实现

锋哥原创的PyQt6图书管理系统视频教程&#xff1a; PyQt6图书管理系统视频教程 Python桌面开发 Python入门级项目实战 (无废话版) 火爆连载更新中~_哔哩哔哩_bilibiliPyQt6图书管理系统视频教程 Python桌面开发 Python入门级项目实战 (无废话版) 火爆连载更新中~共计24条视频&…

C++构造和折构函数详解,超详细!

个人主页&#xff1a;PingdiGuo_guo 收录专栏&#xff1a;C干货专栏 大家龙年好呀&#xff0c;今天我们来学习一下C构造函数和折构函数。 文章目录 1.构造函数 1.1构造函数的概念 1.2构造函数的思想 1.3构造函数的特点 1.4构造函数的作用 1.5构造函数的操作 1.6构造函数…

k8s -ingress

概念 Ingress 公开了从集群外部到集群内服务的 HTTP 和 HTTPS 路由&#xff0c;ingress能代理集群为内部的网络&#xff0c;将集群外部的HTTP/HTTPS网络请求转发至不同的service&#xff0c;其本质就是创建一个NodePort类型的svc,和一个nginx 组成 k8s中的ingress 其实是指…

c语言:全局变量与局部变量重名

结论&#xff1a; 作用域小的覆盖作用域大的&#xff0c;顺带一提&#xff0c;在C中&#xff0c;调用全局的变量前面要加:: #include <stdio.h> using namespace std;int a, b; void fun() {a 100;b 200; }int main() {int a 5, b 7;fun();printf("%d %d\n&quo…

Linux操作系统基础(十):Linux系统信息

文章目录 Linux系统信息 一、时间和日期 1、date时间 2、cal日历 二、磁盘、内存信息 Linux系统信息 本篇文章内容主要是为了方便通过远程终端维护服务器时, 查看服务器上当前 系统日期和时间 / 磁盘空间占用情况 /程序执行情况。 学习终端命令都是查询命令, 通过这些命…

假期day7

设计qq界面 代码 ui->lab1->setPixmap(QPixmap(":/pictrue/denglu.webp"));ui->lab1->setScaledContents(true);ui->lab2->setPixmap(QPixmap(":/pictrue/passwd.jpg"));ui->lab2->setScaledContents(true);ui->lab3->setP…

Python API的使用简述

文章目录 Web APIGit 和 GitHub使用 API 调用请求数据安装 requests处理响应 API处理响应字典监视API的速率限制使用 Pygal 可视化仓库改进Pygal图表添加自定义工具提示 本篇文章&#xff1a;我们叙述如何编写一个独立的程序&#xff0c;并对其获取的数据进行可视化。这个程序将…

《统计学简易速速上手小册》第4章:假设检验(2024 最新版)

文章目录 4.1 假设检验的基本概念4.1.1 基础知识4.1.2 主要案例&#xff1a;新饮料偏好测试4.1.3 拓展案例 1&#xff1a;教育方法的效果比较4.1.4 拓展案例 2&#xff1a;工作满意度调查 4.2 常见的假设检验4.2.1 基础知识4.2.2 主要案例&#xff1a;产品包装改进的效果评估4.…

考研数据结构笔记(7)

循环链表、静态链表、顺序表和链表的比较 循环链表循环单链表循环双链表 静态链表什么是静态链表如何定义一个静态链表&#xff1f;简述基本操作的实现 顺序表和链表的比较逻辑结构物理结构/存储结构数据的运算/基本运算创建销毁增加、删除查找 循环链表 循环单链表 循环双链表…

前端JavaScript篇之ajax、axios、fetch的区别

目录 ajax、axios、fetch的区别AjaxAxiosFetch总结注意 ajax、axios、fetch的区别 在Web开发中&#xff0c;ajax、axios和fetch都是用于与服务器进行异步通信的技术&#xff0c;但它们在实现方式和功能上有所不同。 Ajax 定义与特点&#xff1a;Ajax是一种在无需重新加载整个…

2023年全国职业院校技能大赛软件测试赛题第3套

2023年全国职业院校技能大赛 软件测试赛题第3套 赛项名称&#xff1a; 软件测试 英文名称&#xff1a; Software Testing 赛项编号&#xff1a; GZ034 归属产业&#xff1a; 电子与信息大类 …

第2集《佛说四十二章经》

请大家打开讲议第二面&#xff0c;二、经文大意。 在正式讲解经文之前&#xff0c;先说明本经的修学纲要。本经的经文大意共分三段&#xff0c;第一段是总标&#xff0c;第二段是别明&#xff0c;第三段是结劝。总标又分两小段&#xff0c;先看第一小段。 是经顿渐兼收。首唱…