java基础
待补
文章目录
前言
lambda表达式提供更简洁的语法让我们快速实现方法,流处理可以让我们快速处理批量的数据。
1lambda表达式
1.1 lambda表达式简介
lambda表达式使用简化的格式实现抽象方法
格式:
//无参方法
()->结果表达式
//有参方法
(参数1,参数2……)->结果表达式
当方法逻辑比较复杂时,也可以将结果表达式换成方法体(代码块)
1.2 lambda表达式实现函数式接口
函数式接口:
函数式接口指的是只包含一个抽象方法的接口
可以自定义一个函数式接口,并用lambda表达式来实现它,如:
interface SayHi {
//函数式接口中提供了一个无参抽象方法
String say();
}
interface ADD {
//函数式接口中提供一个有参抽象方法
int Add(int a, int b);
}
public class test {
public static void main(String[] args) {
//用lambda表达式重写无参抽象方法say(),即使重写无参方法,也要带有()
SayHi pi = () -> "你好";
//使用实现对象pi调用重写好的方法say()
sout(pi.say());
//使用lambda表达式重写Add方法
ADD a = (x, y) -> x + y;
//调用重写好的Add()方法
sout(a.Add(7, 5));
}
}
以上使用在方法逻辑简单的情况下,如果要重写复杂的方法逻辑,可以在->后跟上**{}方法体**
1.3lambda表达式调用外部变量
使用lambda重写方法时,可以访问到外部的变量,但是lambda表达式不能修改局部变量,可以修改成员变量,如:
//测试用的函数式接口以及抽象方法
interface VariableInterface{
void method();
}
public class VariableDemo1{
//定义VariableDemo1类的成员变量value2
int value2=200;
public satic void main(String[] args){
//定义main方法中的局部变量value1
int value1 = 100;
VariableInterface v=()->{
//在lambda表达式中value1和vlaue2都可以使用
int num =value1-90;
//value1是main方法的局部变量,lambda不能修改其值,这里会报错
value1=12;
//value2是成员变量,lambda可以修改其值
value2=20;
return num;
}
sout(v.method());
}
}
1.4 lambda表达式与异常处理
当函数式接口的抽象方法会抛出异常时,使用lambda在重写该抽象方法时也要抛出相同异常,如:
以下案例模拟未成年防沉迷系统,抽象方法checkAge()会检测传入数据是否大于18,小于18则抛出自定义异常
impoot java.util.Scanner
//自定义未成年异常
class UnderAgeException extends Exception{
public UnderAgeException(String message){
super(message)
}
}
//定义函数式接口和抽象方法
interface AntiaddictInterface{
boolean checkAge(int age)throws
}
//主方法测试
public class ThrowExceptionDemo{
public static void main(String[] args){
//使用lambda重写抽象方法,在传入数字小于18时抛出自定义异常
AntiaddictInterface ai =(a)->{
if(a<18){
throw new UnderAgeException("未满18岁");
}else{
sout("已满18岁");
}
}
//调用重写好的checkAge()方法,传入值12,结果会抛出自定义异常
//UnderAgeException
ai.checkAge(12);
}
}
2方法的引用
lambda表达式提供了方法的引用,来指定使用一个已经存在的方法逻辑重写函数式接口的抽象方法,使用这个已存在方法的逻辑来重写函数式接口中的抽象方法,使用符号:: (双冒号)进行方法的引用
2.1引用静态方法
引用静态方法的格式为:
类名::静态方法名
如:
//测试用函数式接口
interface StaticMethodInterface {
int method(int a, int b);
}
//定义StaticMethodeDemo类,其中定义了要引用的add静态方法
public class StaticMethodeDemo {
static int add(int x, int y) {
return x + y;
}
public static void main(String[] args) {
//使用StaticMethodDemo::add来引用静态方法add
StaticMethodInterface sm = StaticMethodDemo::add;
//调用方法method,其执行逻辑和所引用静态方法add一样
int result = sm.method(15, 16);
sout(result);
}
} sout(result); } }
2.2引用成员方法
引用成员方法的格式为:
对象名::成员方法名
如:
import java.text.SimpleDateFormat
import java.util.Date
//测试用函数式接口
interface InstanceMethodInterface{
String method(Date date);
}
public class InstanceMethodDemo{
//要引用的成员方法,用于把传入的Date对象转换为yyyy-MM-dd格式
public String format(Date date){
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
return sdf.format(date);
}
public static void main(Stirng[] args){
//与引用静态方法不同的是,要引用成员方法先要有类的实例对象
//这里创建名为demo的对象
InstanceMethodDemo demo = new InstanceMethodDemo();
//调用成员方法format
InstanceMethodInterface im = demo::format;
//创建Date对象
Date date=new Date();
//传入Date对象测试
sout(im.method(date));
}
}
2.3引用带泛型的方法
还可以引用带泛型的方法,格式:
类名::<泛型>静态方法名
对象名::<泛型>成员方法名
如:
import java.util.HashSet;
//测试用函数式接口,因为要引用带泛型的方法,则表示函数式接口中的抽象方法也会用到泛型
interface ParadigmInterface{
//此处接收的参数是一个数组对象
int method(T[] t)
}
public class ParadigmDemo{
//要引用的带泛型的静态方法,接收一个数组对象
static public int repeatCoount(T[] t){
//获取传入数组的长度
int arrayLenth=t.lenth;
//创建一个HashSet对象,HashSet集合不允许元素重复
java.util.HashSet set=new HashSet<>();
//遍历数组t,并把其元素一个个传入HashSet集合中
//set集合会自动删除多余的重复对象
for(T tmp:t){
set.add(tmp);
}
//用原数组长度减去新的set对象长度,可以得到被删除了多少个重复元素
return arrayLenth-set.size();
}
public static void main(String[] args){
//创建整数类型的数组
Integer a[]={1,1,2,3};
//创建字符串类型的数组
String s[]={"王",“李”,“陈”,“陈”,“王”};
//第一次引用静态方法时传入的泛型为Integer
ParadigmInterface p1=ParadigmDemo:: repeatCoount;
sout("整数数组重复元素个数为:"+p1.method(a));
//第二次引用静态方法时传入的泛型为String,可以省略::后的泛型指定,
//如果省略::后的泛型指定,会默认使用前面函数接口使用的泛型
ParadigmInterface p2=ParadigmDemo::repeatCoount;
sout("字符串数组中重复的元素个数为:"+p2.method(s));
}
}
2.4引用构造方法
引用构造方法格式:
类名::new
该格式把无参构造方法和有参构造方法都引用了
2.5 Function接口
想要使用lambda表达式需要先定义函数式接口,官方提供了Function接口作为函数式接口来快速使用lambda表达式,如:
以下例子用来拼接ip地址
import java.util.function.Function;
public class FunctionDemo{
//用lambda表达式实现Function接口
//前一个泛型指定传入参数为整数数组,后一个泛型指定最终返回结果类型为字符串
Function function=(n)->{
StringBuilder str = new StirngBuilder();
//把传入的整数数组加进字符串,并在每个数字后面加上.
for(Integer num:n){
str.append(num);
str.append('.');
}
//去除字符串最后多余的.
str.deleteCharAt(str.lenth()-1);
//返回拼接好的ip
return str.toString;
};
public static void main(String[] args){
//定义要传入的整数字符串
Integer[] ip={192,168,1,1};
FunctionDemo demo = new FunctionDemo();
//调用重写好的方法
sout(demo.function.apply(ip))
}
}
Function<T,R>接口:接口提供了两个泛型T和R,T用来指定传入参数类型,R用来指定返回值类型。且其中的抽象方法为apply(T t);
上面的例子,T为Integer[],R为String,传入整数数组,表示返回字符串对象
3流处理
流处理的功能类似于sql语句的功能,可以对流中的数据进行查找,删除,管理等,而集合对象可以转换为流对象,进而使用流处理。
于是,我们可以先把数据存储进集合中,然后转换为Stream流,再使用流提供的方法对数据进行处理。
3.1获取流对象
要进行流操作,需要先把数据放到一个stream流对象中,不同存放方式的数据有不同的创建stream流的方法
- 单列集合——stream()
- 数组——stream(T[] array)
- 一堆零散数据——of(T… values)
3.2中间方法
常用的中间方法如下
3.3终结方法
总结
本篇介绍了一下java中的lambda表达式和stream流的常用方法。