day23TCP?UDP,正则表达式,函数式接口,lambda接口,StreamAPI

网络编程

java是internet上的语言,它聪慧语言级上提供了对网络应用程序的支持,程序员能够很容易开发常见的网络应用程序。
java提供的网络类库,可以实现无痛的网络链接,联网的底层被隐藏在Java本地的安装系统中,由jvm进行控制,并且java实现了一个跨平台的网络库,程序员面对的是一个统一的网络编程环境。
网络编程中有两个主要的问题:
如何准确的定位网络上的一台或多台主机,定位主机上的特定的应用;
找到主机后如何可靠高效的进行数据传输。
网络通信有一定的规则,有两套参考模型;OSI参考模型,模型过于理想化,未能在因特网上进行广泛推广;TCP/IP协议,事实上的国际标准。
IP地址是计算机上的唯一标识,ip地址分类方式:公网地址和私有化地址。
端口号:是正在计算机上运行的进程,分为公认端口(0-1023);注册端口(1024-49151);动态/私有端口49152-65535。
端口号与IP地址的组合得出一个网络套接字,Socket。
TCP/IP协议以两个主要的协议,传输控制协议和网络互联协议而得名,实际上是一组协议,包括多个具有不同功能且位互联的协议。
IP协议是网络层的主要协议,支持网间互连的数据通信。
TCP/IP协议从更使用的角度出发,形成了高效的四层体系结构,即物理链路层,IP层,传输层,应用层。

Socket

利用套接字开发网络应用程序,唯一标识的IP地址和端口号组合成唯一能够识别的标识符套接字,通信两端都有socket,是两台机器间通信的端点,网络通信其实就是socket之间的通信,socket允许程序把网络链接当成一个流,数据在两个socket间通过IO传输,一般主动发起通信的应用程序属于客户端,等待通信请求的的为服务端。
Socket分为流套接字使用TCP提供可依赖的字节流服务数据报套接字;字使用UDP提供“尽力而为”的数据报服务。
常用构造器:
Socket(InetAddress address,int port)创建一个流套接字,并将其链接到指定IP地址的指定端口号。
Socket(String host,int port)创建一个流套接字,并将其链接到指定主机上指定的端口号。
常见方法:
inputStream getInputStream返回此套接字的输入流,可以用于接收网络信息;
OutputStream getOutputStream返回此套接字的输出流,可以用于返回网络信息;
InetAddress getInetAddress此套接链接到的远程IP地址,如果没有链接,返回null。
InetAddress geLocalAddress获取套接字本地地址;
int getPort此套接字链接的远程端口号,如果未绑定返回0;
int getLocalPort返回此套接字连接到的本地端口,如果没有绑定,返回-1;
close关闭套接字;
shutdownInput如果在套接字上调用shutdownInput后从套接字输入流读取内容,则流将返回EOF。
shutdownOutput禁用此套接字的输出流。
socket工作过程包括四个基本步骤:
创建socket,打开链接到socket的输入输出流,按照一定的协议对socket就那些读写操作;关闭socket。
服务器程序工作过程包括四个基本步骤:
调用serversocekt(int port);调用accept监听链接请求,调用socket类对象的getOutputStream和getIntputStream获取输出流和输入流;关闭serverSocket和sokcet对象。
服务器必须先建立一个等待刻画u但请求的套接字链接的serversocket对象。

UDP

DatagramSocekt和DatagramPacket实现了基于UDP协议网络程序;
UDP数据包通过数据包套接字DatagramSocket进行发送和接受,系统不保证UDP数据报一定能够安全的送到目的地,也不能确定什么时候可以抵达。
DatagramPacket对象封装了UDP数据包,在数据包中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号。
UDP协议中每个数据包都给出完整的地址信息,因此无须建立发送方和接收方的链接。
常用方法
Datagramsocket(int port)创建数据包套接字,并将其绑定到本地主机上的指定端口,套接字被绑定到通配符地址,IP地址由内核来选择;
DatagramSocket(int port,inetAddress iaddr)创建数据报套接字,将其绑定到本地地址,本地端口号必在0-65535之间,如果IP地址为0.0.0.0,套接字将被绑定到通配符地址,IP地址由内核决定。
close关闭此数据报套接字;
send(DatagramPacket p)从此套接字上发送数据包。
receive(DatagramPacket p)从此套接字接收数据报包,此方法返回时,缓冲区填充接受的数据。
InetAddress getLocalAddress获取套接字绑定的本地地址;
int getLocalPort获取套接字的本地主机上的端口号;
InetAddress getInetAddress返回此套接字上链接的地址;
int getPort返回此套接字的端口;
DatagramPacket(byte[] buf,int length)构造DatagramPacket用来接受长度为length的数据包。
DatagramPacket(byte[] buf,int length,InetAddress address,int port)构造数据包,用来将长度为length的包发送到指定的主机上的指定端口号。
InetAddress getAddress返回某机器的IP地址,此数据报将要法网该机器,或者是从该机器接收到的。
int getPort返回某台远程主机的端口号;
byte[] getData返回数据缓冲区,接收到的或者将要发送的数据据从缓冲区中的偏移量offset处开始,持续length长度。
UDP通信流程
datagramsocket与datagrampacket;建立发送端,接收端;建立数据包;调用socket的发送接受方法;关闭socket。
*比较
TCP协议需要先建立TCP协议,形成传输数据通道,而UDP则是把数据,源,目的封装成数据包,不需要建立链接;
TCP协议采用三次握手,是可靠的,而UDP则是不可靠的;
TCP协议在客户端和服务端间传递信息,而UDP协议则用于广播发送;
TCP协议传输完后释放已经建立的链接,效率低,UDP则无需释放资源,开销小,速度快。

正则表达式

正则表达式定义了字符串的模式,它可以用来搜索,编辑和处理文本;
\大多是转义字符;
^匹配输入字符串开始的位置;
$匹配字符串结束的位置;
*匹配子表达式任意次;
+匹配前面的子表达式一次或者多次;
?匹配前面的子表达式零次或是一次;
{n}n是非负整数,表示匹配确定的n次;
{n,}n是非负整数,至少匹配n次;
{n,m}非负整数,而且n<=m,则至少匹配n次,最大匹配m次;
.匹配除了“\r\n”之外的任何单个字符;
(pattern)匹配pattern并获取这一匹配;
(?:pattern)匹配pattern但不获取匹配结果;
(?=pattern)在任何不匹配pattern的字符串开始处匹配查找字符串;
(?<=pattern)反向肯定预查,只是方向相反;
(?<!pattern)反向否定预查,与正向否定预查类型,只是方向相反;
x|y匹配x或者y;
[xyz]字符集合,匹配所包含的任意一个字符;
[^xyz]负值字符集合,匹配未包含的任意字符;
[a-z]字符范围,匹配指定范围的任意字符;
[^a-z]负值字符范围,匹配任何不在指定范围内的任意字符;
\b匹配一个单词边界;
\B匹配非单词边界;
\cx匹配由x指明的控制字符;
\d匹配一个数字字符;
\D匹配一个非数字字符;
\f匹配一个换页符;
\n匹配一个换行符;
\r匹配一个回车符;
\s匹配任何不可见字符;
\S匹配任何可见字符;
\t匹配一个制表符;
\v匹配一个垂直制表符;
\w匹配包括下划线的任何单词字符;
\W匹配任何非单词字符;
\xn匹配n,其中n为十六进制转义值;
\num匹配num,其中num是一个正整数,是对所获取的匹配的引用;
\un匹配n,其中n是一个用四个十六进制数字表示的unicode字符;
<>匹配单词的开始和结束;
()将(和)之间的表达式定义为组;
|将两个匹配条件进行逻辑或运算;
+匹配1或多个正好在它之间的那个字符;
?匹配0或1正好在它之前的那个字符;
{i}{i,j}匹配指定的数目的字符;
Java源代码的字符串的反斜线被解释为Unicode转移或者其他字符转义,因此必须在字符串字面值中使用两个反斜线,表示正则表达式受到保护,不被Java字节码编译器解释,当解释为正则表达式,字符串字面值“\b”与单个退格字符匹配,而“\b”与单词边界匹配,字符串字面值"(hello)"是非法的,将导致编译时错误;要与字符串匹配,必须使用字符字串字面值。
小括号,匹配小括号内的字符串,可以是一个,也可以是多个,常跟“|”搭配使用,是多选结构的;
中括号,匹配字符组内的字符;
大括号,匹配次数;
Java正则类封装
PatternSyntaxException是一个非强制异常类,它表示一个正则表达式中的语法错误;
Pattern用于创建一个正则表达式,也可以说创建一个匹配模式,它的构造方法是私有的,不可以直接创建;
可以通过Pattern.compile(String regex)创建一个正则表达式;
只能做一些简单的匹配操作;
Pattern.split(CharSequence input)成员方法,用于分隔字符串;
Pattern.matches(String regex,CharSequence input)静态方法,用于快速匹配字符串,该方法适用于只匹配一次,且匹配全部字符串;
Matcher类的构造方法也是私有的,不能随意创建,只能通过Pattern.matcher(CharSequence input)方法得到该类的实例,Matcher m = p.macher(“aaaab”);
支持便捷强大的正则匹配操作,包括分组,多次匹配支持;
Matcher.matches()对整个字符串进行匹配,只有整个字符串都匹配了才返回true;
Matcher.lookingAt()对前面的字符串进行匹配,只有匹配到的字符串在最前面才返回true;
Matcher.find()对字符串进行匹配,匹配到的字符串可以在任何位置;

Lambad表达式

lambda是一个匿名函数,我们可以把lambda表达式理解为一段可以传递的代码。
在java8之后引入了一种新的语法元素和操作符,这个操作符为“->”该操作被称为lambda操作符或者是箭头操作符,它将lambda分为两个部分,左侧指定了lambda表达式需要的参数列表,右侧指定了lambda体,是抽象方法的实现逻辑,也是lambda表达式需要执行的功能。
语法格式
无参,无返回值:()->{};
lambda需要一个参数,但是没有返回值(String str)->{};
数据类型可以省略,编译器可以推断出来:(str)->{};
lambda若只需要一个参数,参数的小括号可以省略:str->{};
lambda需要两个或者以上的参数,多条执行语句,并且可以有返回值:(x,y)->{return;};
lambda只有一条语句,renturn和大括号若有,都可以省略:(x,y)->;
就好像我们遍历时,循环体中是我们要做的事,重点就是我们需要指明怎么做,循环遍历还是靠底层实现;1.8简化之后,就可以再简化一些,你不用管循环了,只需要跟我们说你要做什么,我自动会帮你循环调用。
上述的lambda表达式的参数类型都是由编译器推断出来的,lambda表达式中无需指定类型,程序依然可以编译,这是因为javac根据程序的上下文,在后台推断出参数的类型,lambda表达式的类型依赖于上下文环境,是由编译器推断出来的,这就是所谓的“类型推断”。

函数式(Function)接口

只包含一个抽象方法的接口,称为函数式接口,你可以通过lambda表达式来创建该接口的对象,若lambda表达式抛出一个受检异常,那么该异常需要在目标接口的抽象方法上进行声明;我们可以在一个接口上使用@Functionallnterface注解,这样可以检查它是否是一个函数式接口,同时javadoc也会包含一条声明,说明这个接口是一个函数式接口。
java从诞生日起就是一直倡导,在java里面面向对象编程就是一切,但是随着python,scala等语言的兴起或者是新技术的挑战,java不得不做出调整以便支持更加广泛的技术要求,也即java不但可以支持oop还可以支持oof。
在函数式编程语言中,函数也被当做一等公民对待,在将函数作为一等公民的编程语言中,lambda表达式的类型也是函数,但是在java8中,有所有的对象类型,函数式接口。
简单的来说,lambda表达式就是函数式接口的实例,这就是lambda表达式和函数式接口的关系,也就是说,只要一个对象是函数式接口的实例,那么该对象就可以用lambda表达式来表示;所以以前用匿名实现类表示的现在都可以用lambad表达式来写。
作为参数传递lambad表达式:
作为参数传递lambda表达式,为了将lambda表达式作为参数传递,接收lambda表达式的参数类型必须是在lambda表达式兼容的函数式接口的类型。
方向引用
当要传递lambda体的操作,已经有实现的方法中的,可以使用方法引用!
方法引用可以看作是lambda表达式深层的表达,换句话来说,方法引用就是lambda表达式,也就是函数式接口的一个实例,通过方法的名字来指向一个方法,可以认为是lambda表达式的一个语法糖。
要求:实现接口的抽象方法的参数列表和返回值类型,必须与方法引用的方法的参数列表和返回类型保持一致。
格式:使用操作符::将类或者是对象与方法名分开;
对象::实例方法名;
类::静态方法名;
类::实例方法名;
当函数式接口方法的第一个参数是需要引用方法的调用者,并且第二个参数是需要引用方法的参数(无参)的时候ClassName::methodName
构造器引用
ClassName::new
与函数式接口相结合,自动与函数式接口中方法兼容,可以把构造器引用赋值给定义的方法,要求构造器参数列表要与接口中抽象方法的参数列表一致,且方法的返回值为构造器对应类的对象;

强大的StreamAPI

StreamAPI说明:java8中有两个最为重要的改变,第一个就是lambda表达式,另外一个则是streamAPI;
它把真正的函数式编码风格引入到Java中,这是目前为止对java类库最好的补充,因为streamAPI可以极大的提供java程序员的生产力,让程序员写出更加高效干净简洁的代码。
Stream是java8中集中处理的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找,过滤,映射数据等操作,使用streamApi对集合数据进行操作,就类似与使用sql执行的数据库查询,也可以使用streamApi来并行执行操作,简单来说,steamApi就是提供了一种高效且易于使用的处理数据的方式。
为什么使用streamAPI
实际开发中,很多数据源都来自mysql,oracle等,大门时现在的数据源更多了,有mongDB,radis等,这些Nosql的数据就需要java层去处理。
Stream和Colleciton集合的区别:Collection是一种静态的内存数据结构,而stream是有关计算的,前者是主要面向内存,而后者则是主要面向cpu的,通过cpu进行计算。
Stream是数据渠道,是用于操作数据源锁生成的元素序列,集合讲的是数据,而stream讲的是计算;
stream不会自己存储元素,不会改变源对象,相反,他们会返回Uighur持有结果是新stream;操作是延迟执行的,这意味着他们会等到需要结果的时候才执行。
步骤:
创建stream;中间操作,终止操作。

java8之后,collection接口被扩展,提供了两中获取流的方法:default Stream stream()返回一个顺序流,default Stream parallelStream返回一个并行流。
通过Arrays的静态方法stream可以获取数组流,重载形式,能够处理对应的基本类型的数组;
通过Stream的of通过显示值创建一个流,它可以接受任何数量的参数;
可以使用静态方法Stream.itera和Stream.gemerate创建无限流;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卑微-程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值