UDP通信原理:UDP协议是一种不可靠的网络协议,它在通信的两端各简历一个Socket对象,但是这两个Socket只是发送,接收数据的对象
基于UDP协议的通信双方,没有所谓的客户端和服务器概念
Java提供DatagramSocket类最为基于UDP协议的Socket
UDP发送数据
发送数据的步骤
1.创建发送端的Socket对象(DatagramSocket)
DatagramSocket()
2.创建数据,并把数据打包
DatagramSocket(byte[] buf, int length,InetAddress address,int port)
3.调用DatagramSocket对象的方法发送数据
void send(DatagramPacket p)
4.关闭发送端
void close()
public class Demo {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket();
byte[] bys = "helloworld".getBytes();
// int length = bys.length;
// InetAddress m = Inet4Address.getByName("m");
// int port = 10086;
// DatagramPacket dp = new DatagramPacket(bys,length,m,port);
DatagramPacket dp = new DatagramPacket(bys,bys.length,Inet4Address.getByName("m"),10086);
//发送数据报包
ds.send(dp);
ds.close();
}
}
UDP接收数据
接收数据的步骤
1.创建接收端的Socket对象(DatagramSocket)
DatagramSocket()
2.创建一个数据包,用于接收数据
DatagramPacket(byte[] buf, int length) 构造一个 DatagramPacket用于接收长度为 length数据包
3.调用DatagramSocket对象的方法接收数据
void receive(DatagramPacket p) 从此套接字接收数据报包
4.解析数据包,并把数据在控制台显示
byte[] getData() 返回数据缓冲区。
int getLength() 返回要发送的数据的长度或接收到的数据的长度。
5.关闭接收端
void close();
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket(10086);
//DatagramPacket(byte[] buf, int length) 构造一个 DatagramPacket用于接收长度为 length数据包。
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys,bys.length);
//void receive(DatagramPacket p) 从此套接字接收数据报包。
ds.receive(dp);
//byte[] getData() 返回数据缓冲区。
// byte[] data = dp.getData();
//int getLength() 返回要发送的数据的长度或接收到的数据的长度。
// int len = dp.getLength();
// String dataString = new String(data,0,len);
// System.out.println(dataString);
System.out.println(new String(dp.getData(),0,dp.getLength()));
ds.close();
}
}
UDP通信程序练习
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
while (true){
DatagramSocket ds = new DatagramSocket(10086);
//DatagramPacket(byte[] buf, int length) 构造一个 DatagramPacket用于接收长度为 length数据包。
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys,bys.length);
//void receive(DatagramPacket p) 从此套接字接收数据报包。
ds.receive(dp);
System.out.println(new String(dp.getData(),0,dp.getLength()));
ds.close();
}
}
}
public class Demo {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket();
//自己封装键盘录入数据
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line;
while ((line = br.readLine())!=null){
if ("886".equals(line)){
break;
}
byte[] bys = line.getBytes();
DatagramPacket dp = new DatagramPacket(bys,bys.length,Inet4Address.getByName("m"),10086);
//发送数据报包
ds.send(dp);
}
ds.close();
}
}
TCP通信原理
TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket对象,从而在通信的两端形成网络虚拟链路,一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信
Java对基于TCP协议的网络提供了良好的封装,使用Socket对象来代表两端的通信端口,并通过Socket产生IO流来进行网络通信
Java位客户端提供了Socket类,位服务器端提供了ServerSocket类
TCP发送数据
1.创建客户端的Socket对象(Socket)
Socket(InetAddress address, int port) 创建流套接字并将其连接到指定IP地址的指定端口号。
Socket(String host, int port) 创建流套接字并将其连接到指定主机上的指定端口号。
2.获取输出流,写数据
OutputStream getOutputStream() 返回此套接字的输出流。
3.释放资源
void close();
public static void main(String[] args) throws IOException {
// Socket(InetAddress address, int port) 创建流套接字并将其连接到指定IP地址的指定端口号。
// Socket s = new Socket(Inet4Address.getByName("m"),10086);
//Socket(String host, int port) 创建流套接字并将其连接到指定主机上的指定端口号。
Socket s = new Socket("m",10086);
//获取输出流,写数据
//OutputStream getOutputStream() 返回此套接字的输出流。
OutputStream os = s.getOutputStream();
os.write("hello".getBytes());
s.close();
}
TCP接收数据
1.创建服务器端的Socket对象(ServerSocket)
ServerSocket(int port) 创建绑定到指定端口的服务器套接字。
2.监听客户端连接,返回一个Socket对象
Socket accept() 侦听要连接到此套接字并接受它。
3.获取输入流,读数据,并把数据显示在控制台
InputStream getInputStream() 返回此套接字的输入流。
4.释放资源
void close()
public static void main(String[] args) throws IOException {
//ServerSocket(int port) 创建绑定到指定端口的服务器套接字。
ServerSocket ss = new ServerSocket(10086);
//Socket accept() 侦听要连接到此套接字并接受它。
Socket s = ss.accept();
//获取输入流,读数据,并把数据显示在控制台
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len;
while ((len = is.read(bys))!=-1){
String data = new String(bys,0,len);
System.out.println(data);
}
s.close();
ss.close();
}
TCP通信程序练习
public static void main(String[] args) throws IOException {
// Socket(InetAddress address, int port) 创建流套接字并将其连接到指定IP地址的指定端口号。
// Socket s = new Socket(Inet4Address.getByName("m"),10086);
//Socket(String host, int port) 创建流套接字并将其连接到指定主机上的指定端口号。
Socket s = new Socket("m",10086);
//获取输出流,写数据
//OutputStream getOutputStream() 返回此套接字的输出流。
OutputStream os = s.getOutputStream();
os.write("hello".getBytes());
//接收服务器反馈
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len = is.read(bys);
String data = new String(bys,0,len);
System.out.println("客户端:"+data);
// int len;
// while ((len = is.read(bys))!=-1){
// String data = new String(bys,0,len);
// System.out.println("客户端:"+data);
// }
s.close();
os.close();
is.close();
}
public static void main(String[] args) throws IOException {
//ServerSocket(int port) 创建绑定到指定端口的服务器套接字。
ServerSocket ss = new ServerSocket(10086);
//Socket accept() 侦听要连接到此套接字并接受它。
Socket s = ss.accept();
//获取输入流,读数据,并把数据显示在控制台
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len = is.read(bys);
String data = new String(bys,0,len);
System.out.println("服务器:"+data);
// int len;
// while ((len = is.read(bys))!=-1){
// String data = new String(bys,0,len);
// System.out.println("服务器:"+data);
// }
//给出反馈
OutputStream os = s.getOutputStream();
os.write("收到".getBytes());
s.close();
ss.close();
os.close();
}
数据键盘录入+接收生成文本文件练习
public class Demo {
public static void main(String[] args) throws IOException {
Socket s = new Socket("192.168.31.77",10086);
//获取输出流,写数据
//OutputStream getOutputStream() 返回此套接字的输出流。
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//封装输出流对象
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line;
while ((line = br.readLine())!=null){
if ("886".equals(line)){
break;
}
bw.write(line);
bw.newLine();
bw.flush();
//接收服务器反馈
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len = is.read(bys);
String data = new String(bys,0,len);
System.out.println("客户端:"+data);
}
s.close();
}
}
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
//ServerSocket(int port) 创建绑定到指定端口的服务器套接字。
ServerSocket ss = new ServerSocket(10086);
//Socket accept() 侦听要连接到此套接字并接受它。
Socket s = ss.accept();
//获取输入流,读数据,并把数据显示在控制台
// InputStream is = s.getInputStream();
// InputStreamReader isr = new InputStreamReader(is);
// BufferedReader br = new BufferedReader(isr);
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter bw = new BufferedWriter(new FileWriter("untitled1\\copy.txt"));
String line;
while((line = br.readLine())!=null){
System.out.println("服务器:"+line);
bw.write(line);
bw.newLine();
bw.flush();
//给出反馈
OutputStream os = s.getOutputStream();
os.write("收到".getBytes());
}
ss.close();
bw.close();
}
}
数据来自于文本文件,接收到的数据写入文本文件
public class Demo {
public static void main(String[] args) throws IOException {
Socket s = new Socket("192.168.31.77",10086);
//封装文本文件的数据
BufferedReader br = new BufferedReader(new FileReader("untitled1\\osw.txt"));
//封装输出流对象
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line;
while ((line = br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
//接收服务器反馈
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len = is.read(bys);
String data = new String(bys,0,len);
System.out.println("客户端:"+data);
}
s.close();
}
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
//ServerSocket(int port) 创建绑定到指定端口的服务器套接字。
ServerSocket ss = new ServerSocket(10086);
//Socket accept() 侦听要连接到此套接字并接受它。
Socket s = ss.accept();
//获取输入流,读数据,并把数据显示在控制台
// InputStream is = s.getInputStream();
// InputStreamReader isr = new InputStreamReader(is);
// BufferedReader br = new BufferedReader(isr);
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter bw = new BufferedWriter(new FileWriter("untitled1\\copy.txt"));
String line;
while((line = br.readLine())!=null){
System.out.println("服务器:"+line);
bw.write(line);
bw.newLine();
bw.flush();
//给出反馈
OutputStream os = s.getOutputStream();
os.write("收到".getBytes());
}
ss.close();
bw.close();
}
}
数据来自于文本文件,接收到的数据写入文本文件+给出反馈
public class Demo {
public static void main(String[] args) throws IOException {
Socket s = new Socket("192.168.31.77",10086);
//封装文本文件的数据
BufferedReader br = new BufferedReader(new FileReader("untitled1\\osw.txt"));
//封装输出流对象
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line;
while ((line = br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
}
//自定义结束标识
// bw.write("886");
// bw.newLine();
// bw.flush();
//void shutdownOutput() 禁用此套接字的输出流。(输出结束)
s.shutdownOutput();
//接收服务器反馈
BufferedReader brus = new BufferedReader(new InputStreamReader(s.getInputStream()));
String data = brus.readLine();
System.out.println("服务器的反馈:"+data);
s.close();
}
}
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
//ServerSocket(int port) 创建绑定到指定端口的服务器套接字。
ServerSocket ss = new ServerSocket(10086);
//Socket accept() 侦听要连接到此套接字并接受它。
Socket s = ss.accept();
//获取输入流,读数据,并把数据显示在控制台
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter bw = new BufferedWriter(new FileWriter("untitled1\\copy.txt"));
String line;
while((line = br.readLine())!=null){
if ("886".equals(line)){
break;
}
System.out.println("服务器:"+line);
bw.write(line);
bw.newLine();
bw.flush();
}
//给出反馈
BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
bwServer.write("上传成功");
bwServer.newLine();
bwServer.flush();
ss.close();
bw.close();
}
}
出现程序一直等待的问题,(原因是读数据的方法是阻塞式的)
解决办法:自定义结束标记;使用void shutdownOutput() 禁用此套接字的输出流。(输出结束)方法
多线程实现文件上传练习(客户端与上一练习相同)
public class ServerThread implements Runnable {
private Socket s;
public ServerThread(Socket s) {
this.s=s;
}
@Override
public void run() {
try {
//BufferedWriter bw = new BufferedWriter(new FileWriter("untitled1\\copy.txt"));
//解决名称冲突问题
int count = 0;
File file = new File("untitled1\\copy["+count+"]txt");
while (file.exists()){
count++;
file = new File("untitled1\\copy["+count+"]txt");
}
BufferedWriter bw = new BufferedWriter(new FileWriter(file));
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
String line;
while ((line=br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
System.out.println("服务器:"+line);
}
//给出反馈
BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
bwServer.write("上传成功");
bwServer.newLine();
bwServer.flush();
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
//ServerSocket(int port) 创建绑定到指定端口的服务器套接字。
ServerSocket ss = new ServerSocket(10086);
while (true){
//Socket accept() 侦听要连接到此套接字并接受它。
Socket s = ss.accept();
//为每一个客户端开启一个线程
new Thread(new ServerThread(s)).start();
}
}
}
Lambda表达式
体验lambda表达式
public class LambdaDemo {
public static void main(String[] args) {
//匿名内部类改写多线程
// new Thread(new Runnable() {
// @Override
// public void run() {
// System.out.println("多线程");
// }
// }).start();
// Lambda表达式的方式改进
new Thread(()->{
System.out.println("多线程");
}).start();
}
}
组成Lambda表达式的三要素:形式参数,箭头,代码块
Lambda表达式格式
格式:(形式参数)—>{代码块}
形式参数:如果有多个参数,参数之间用逗号隔开:如果没有参数,留空即可
->:由应文中画线和大于符号组成,固定写法,代表指向动作
代码块:是我们具体要做的事情,也就是以前我们写的方法体内容
Lambda表达式练习
Lambda表达式的使用前提
有一个接口
接口中有且仅有一个抽象方法
Lanbda表达式的省略模式
省略规则:
参数类型可以省略,但是有多个参数的情况下,不能只省略一个
如果参数有且仅有一个,那么小括号可以省略
如果代码块的语句只有一条,可以省略大括号和分号,甚至是return
注意事项:
使用Lambda必须要有接口,并且要求接口中有且仅有一个抽象方法
必须有上下文环境,才能推导出Lambda对应的接口
根据局部变量的赋值得知Lambda对应的接口:Runnable r =()-> System.out.println("Lambda表达式");
根据调用方法的参数得知Lambda对应的接口:new Thread(()->System.out.println("Lambda")).start();
Runnable r =()-> System.out.println("Lambda表达式");
new Thread(r).start();
new Thread(()->System.out.println("Lambda")).start();
Lambda表达式和匿名内部类的区别
所需类型不同
匿名内部类:可以是接口,也可以是抽象类,还可以是具体类
Lambda表达式:只能是接口
使用限制不同
如果接口中有且仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类
如果接口中多余一个抽象方法,只能使用匿名内部类,而不能使用:Lambda表达式
实现原理不同
匿名内部类:编译之后,产生一个单独的.class字节码文件
Lambda表达式:编译之后,没有一个单独的.class字节码文件,对应的字节码会在运行的时候自动生成
接口组成更新
接口组成更新概述
接口的组成
常量:public static final
抽象方法:public abstract
默认方法(Java8)
静态方法(Java8)
私有方法(Java9)
接口中默认方法
接口中默认方法的定义格式:
格式:public default 返回值类型 方法名(参数类型){ }
范例:public default void show3(){ }
接口中和默认方法的注意事项:
默认方法不是抽象方法,所以不强制被重写。但是可以被重写,重写的时候去掉default关键字
public可以省略,default不能省略
接口中的静态方法
接口中静态方法的定义格式:
格式:public static 返回值类型 方法名(参数列表){ }
范例:public static void show(){ }
接口中静态方法的注意事项:
静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
public 可以省略,static不能省略
接口中的私有方法
接口中私有方法的定义格式:
格式1:private 返回值类名 方法名(参数列表){ }
范例1:private void show() { }
格式2:private static 返回值类型 方法名(参数列表){ }
范例2:private static void method(){ }(静态方法只能调用静态方法)
接口中私有方法的注意事项:
默认方法可以调用私有方法的静态方法和非静态方法
静态方法只能调用私有的静态方法
方法引用
public static void main(String[] args) {
useInter(s->{
System.out.println(s);
});
//方法引用符::
useInter(System.out::println);
//可推导的就是可省略的
}
方法引用符
:: 该符号为引用运算符,而它所在的表达式被称为方法引用
推到与省略
如果使用Lambda,根据“可推导就可省略”原则,无需指定参数类型,也无需指定的重载形式,它们都将自动被推导
如果使用方法引用,也是同样可以根据上下文进行推导
方法引用是Lambda的孪生兄弟
引用类方法(引用类的静态方法)
格式:类名::静态方法
范例:Integer::parseInt
Interger类的方法:public static int parseInt(String)转换为int类型数据
public static void main(String[] args) {
useConverter(s-> Integer.parseInt(s)
);
useConverter(Integer::parseInt);
}
private static void useConverter(Converter c) {
int cn = c.convert("9999");
System.out.println(cn);
}
Lambda表达式被类方法替代的时候,他的形式参数全部传递给静态方法作为参数
引用对象的实例方法
格式:对象::成员方法
范例:"HelloWorld"::toUpperCase
String类中的方法:public String toUpperCase()将此String所有字符转换成大写
public class PrintString {
public void printUpper(String s){
System.out.println(s.toUpperCase());
}
}
public interface Printer {
void PrintUpperCase(String s);
}
public class PrinterDEmo {
public static void main(String[] args) {
// usePrinter((String s)->{
// System.out.println(s.toUpperCase());
// });
//引用对象实例方法
PrintString p = new PrintString();
usePrinter(p::printUpper);
}
private static void usePrinter(Printer p) {
p.PrintUpperCase("HelloWorld");
}
}
Lambda表达式被对象的实例方法替代的时候,它的形参全部传递给该方法作为参数
引用类的实例方法
格式:类名::成员方法
范例:String::substring
String类中的方法:public String substring(int beginIndes,int endIndex)
从beginIndex开始到endIndex结束,截取字符串。返回一个子串,字串的长度为endIndex-beginIndex
public interface MyString {
String mySubString(String s ,int x ,int y);
}
public class MyStringDemo {
public static void main(String[] args) {
// useMyString((s,x,y)->{
// return s.substring(x,y);
// });
useMyString((s,x,y)->s.substring(x,y));
//引用类的实例方法
useMyString(String::substring);
}
private static void useMyString(MyString my){
String s = my.mySubString("HelloWorld", 2, 5);
System.out.println(s);
}
}
Lambda表达式被类的实例方法代替的时候,第一个参数作为调用者,后面的参数全部传递给该方法作为参数
引用构造器(引用构造方法)
格式:类名::new
范例:Student::new
public interface StudentBuilder {
Student build(String name,int age);
}
public class StudentDemo {
public static void main(String[] args) {
// useStudentBuilder((name,age)->{
// return new Student(name,age);
// });
useStudentBuilder(((name, age) -> new Student(name,age)));
//引用构造器
useStudentBuilder(Student::new);
}
private static void useStudentBuilder(StudentBuilder s) {
Student sm = s.build("xiaohuang", 30);
System.out.println(sm.getName()+","+sm.getAge());
}
}
Lambda表达式被构造器替代时,它的形参全部传递给构造器作为参数
函数式接口(Lambda表达式适用):有且仅有一个抽象方法的接口
@FunctionalInterface
public interface MyInterface {
void show();
}
public class MyInterfaceDemo {
public static void main(String[] args) {
MyInterface my = ()-> System.out.println("函数式接口");
my.show();
}
}
@FunctionalInterface 放在接口定义的上方,如果接口是函数式接口,编译通过,如果不是,编译失败
注意:自己在定义函数式接口时,@FunctionalInterface是可选的,不写这个注解,只要保证满足函数式接口的定义条件,一样时函数式接口,建议加上该注解。
函数式接口作为方法的参数
如果方法的参数是一个函数式接口,我们可以使用Lambda表达式作为参数传递
startThread(()->System.out.println(Thrasd.currentThread().getName()+"线程启动"));
函数式接口作为方法的返回值
public class MyInterfaceDemo {
public static void main(String[] args) {
ArrayList<String> ar = new ArrayList<String>();
ar.add("bb");
ar.add("ddddd");
ar.add("aaa");
ar.add("cccc");
System.out.println(ar);
Collections.sort(ar,getComparator());
System.out.println(ar);
}
private static Comparator<String> getComparator(){
//匿名内部类
// Comparator<String> cp = new Comparator<String>() {
// @Override
// public int compare(String o1, String o2) {
// return o1.length()-o2.length();
// }
// };
// return cp;
// return new Comparator<String>() {
// @Override
// public int compare(String o1, String o2) {
// return o1.length()-o2.length();
// }
// };
return (s1,s2)-> s1.length()-s2.length();
}
}
如果方法的返回值是一个函数式接口,我们可以使用Lambda表达式作为返回结果
常用的函数式接口
Supplier接口
Supplier<T>:包含一个无参的方法
T get(); 获得结果
该方法不需要参数,它会按照某种实现逻辑(由Lambda表达式实现)返回一个数据
Supplier<T>接口也被称为生产型接口,如果我们指定了接口的泛型是什么类型,那么接口中get方法就会生产什么类型的数据供我们使用
public static void main(String[] args) {
String s = getString(() -> "xiaobai");
System.out.println(s);
}
private static String getString(Supplier<String> sup){
return sup.get();
}
Consumer接口
Consumer<T>:包含两个方法
void accept(T t): 对给定的参数执行此操作
default Consumer<T>andThen(Consumer after):返回一个组合的Consumer,一次执行此操作,然后执行after操作
Consumer<T>接口也被称为消费型接口,他消费的数据的数据类型由泛型指定
public static void main(String[] args) {
operatorString("xiaohuang",(String s )->{
System.out.println(s);
});
operatorString("xiaolv",s-> System.out.println(s));
operatorString("xiaolan",System.out::println);
operatorString("xiaohei",s->
System.out.println(new StringBuilder(s).reverse().toString()));
operatorString("xiaofen",s-> System.out.println(s),s -> System.out.println(new StringBuilder(s).reverse().toString()));
}
//定义一个方法,用不同的方式消费同一个字符串数据两次
private static void operatorString(String name, Consumer<String> con1,Consumer<String> con2){
// con1.accept(name);
// con2.accept(name);
con1.andThen(con2).accept(name);
}
private static void operatorString(String name, Consumer<String> con){
con.accept(name);
}
练习
public static void main(String[] args) {
String[] sa = {"xiaohong,12","xiaocheng,15","xiaohuang,18"};
printInfo(sa,(String s)->{
String name = s.split(",")[0];
System.out.print("姓名"+name);
},(String s)->{
int age = Integer.parseInt(s.split(",")[1]);
System.out.println(",年龄"+age);
});
}
//定义一个方法,用不同的方式消费同一个字符串数据两次
private static void printInfo(String[] sa, Consumer<String> con1,Consumer<String> con2){
for (String s : sa){
con1.andThen(con2).accept(s);
}
}
Predicate接口
Predicate<T>:常用的四个方法
boolean test(T t):对给定的参数进行判断(判断逻辑由Lambda表达式实现),返回一个布尔值
default Predicate<T> negate():返回一个逻辑地否定,对应逻辑非
default Predicate<T> and(Predicate other):返回一个组合判断,对应短路与
default Predicate<T> or(Predicate other):返回一个组合判断,对应短路或
Predicate<T>接口通常用于判断参数是否满足指定的条件
public static void main(String[] args) {
boolean b = chechString("hellojava", s -> s.length() > 8);
System.out.println(b);
boolean b1 = checkString("helloworld", s -> s.length() > 8, s -> s.length() < 16);
System.out.println(b1);
}
private static boolean chechString(String s , Predicate<String> p){
return p.negate().test(s);
}
private static boolean checkString(String s, Predicate<String> p1, Predicate<String> p2){
// return p1.test(s)&&p2.test(s);
return p1.and(p2).test(s);
}
筛选练习
public static void main(String[] args) {
String[] ss = {"xiaohong,12","xiaocheng,15","xiaohuang,18","xiaolv,17"};
checkString(ss, s -> s.split(",")[0].length() > 8, s -> Integer.parseInt(s.split(",")[1]) > 16);
}
private static void checkString(String[] ss, Predicate<String> p1, Predicate<String> p2){
// return p1.test(s)&&p2.test(s);
boolean test = false;
for (String s : ss) {
test = p1.and(p2).test(s);
if (test){
System.out.println(s);
}
}
}
Function接口
Function<T,R>:常用的两个方法
R apply(T t):将此函数应用于给定的参数
default<T> Function andThen(Function after):返回一个组合函数,首先将该函数应用于输入,然后将after函数应用于结果
Function<T,R>接口通常用于对参数进行处理,转换(处理逻辑由Lambda表达式实现),然后返回一个新的值
public static void main(String[] args) {
convert("555",s->Integer.parseInt(s),s->String.valueOf(s+111));
}
private static void convert(String s, Function<String,Integer> fun1,Function<Integer,String> fun2){
// String ss = fun2.apply(fun1.apply(s));
String ss = fun1.andThen(fun2).apply(s);
System.out.println(ss);
}