网络
- C/S B/S
- 使用IP地址和端口号,保证数据准确无误地发送到对方计算机的指定软件上
- IP地址->小区,端口号->门牌号
- TCP

- 服务器是没有IO流的,获取客户端的
Socket对象,使用其中提供的IO流与客户端进行交互;服务器要明确与哪个客户端交互
- 套接字,包含IP地址和端口号的网络单位
Client
Socket socket = new Socket(InetAddress.getLocalHost(), 3213)
OutputStream outputStream = socket.getOutputStream()
outputStream.write("你好".getBytes())
InputStream inputStream = socket.getInputStream()
byte[] bytes = new byte[1024]
int len = inputStream.read(bytes)
System.out.println(new String(bytes, 0 ,len))
socket.close()
Server
ServerSocket serverSocket = new ServerSocket(3213)
//客户端的socket
Socket socket = serverSocket.accept()
//输出流
OutputStream outputStream = socket.getOutputStream()
//获取输入流,读取客户端发过来的内容
InputStream inputStream = socket.getInputStream()
byte[] bytes = new byte[1024]
int len = inputStream.read(bytes)
System.out.println(new String(bytes, 0 ,len))
//回写
outputStream.write("收到".getBytes())
socket.close()
serverSocket.close()
注意事项
- 在读取文件时候,客户端永远不会读到结束标志,所以导致发给服务器的数据也不会有结束标志,所以要发送结束标志
socket.shutdownOutput();
模拟BS架构
ServerSocket serverSocket = new ServerSocket(8888)
System.out.println(InetAddress.getLocalHost())
//浏览器解析服务器回写的html页面,如果有图片,会单独开启一个线程,读取服务图片
while (true) {
Socket socket = serverSocket.accept()
new Thread(new Runnable() {
@Override
public void run() {
try {
InputStream inputStream = socket.getInputStream()
//读请求头第一行
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))
//切割
String line = bufferedReader.readLine()
System.out.println(line)
//GET /day4-code/src/web/index.html HTTP/1.1 空格分隔;截取字符串,从第一个开始
String htmlpath = line.split(" ")[1].substring(1)
//读取html文件
FileInputStream fileInputStream = new FileInputStream(htmlpath)
OutputStream outputStream = socket.getOutputStream()
//设置响应头
outputStream.write("HTTP/1.1 200 OK\r\n".getBytes())
outputStream.write("Content-Type: text/html\r\n".getBytes())
// 必须要写入空行,否则浏览器不解析
outputStream.write("\r\n".getBytes())
//获取响应体,返回响应体
int len = 0
byte[] bytes = new byte[1024]
//不会读取到结束标记,导致服务器永远收不到结束标记
while ((len = fileInputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0 ,len)
}
fileInputStream.close()
socket.close()
} catch (Exception e) {
e.printStackTrace()
}
}
}).start()
//serverSocket.close()
}
函数式接口
- 有且只有一个抽象方法的接口
@FunctionalInterface修饰接口,保证接口只有一个方法,否则报错
- 使用
Lambda作为接口实现类的语法糖传递,仅仅是把接口形式的参数传递进去
- 作为参数返回
public static void main(String[] args) {
String[] strings = {"31212", "dazxczxc", "dwa2", "312sdazxczxc"};
Arrays.sort(strings, getComparable());
System.out.println(Arrays.toString(strings));
Arrays.sort(strings, ((o1, o2) -> o1.length() - o2.length()));
System.out.println(Arrays.toString(strings));
}
private static Comparator<String> getComparable() {
return (o1, o2) -> o2.length() - o1.length();
}
Supplier
- 生产型接口,指定的接口泛型是什么类型,接口中的get方法就会生产什么类型的数据
public static void main(String[] args) {
String s = getString(() -> "java");
System.out.println(s);
}
public static String getString(Supplier<String> supplier) {
return supplier.get();
}
public static void main(String[] args) {
Integer[] integers = {21231,3,5,7,123,3123,-30}
//重写get方法
Integer maxInteger = getMaxInteger(() -> {
Arrays.sort(integers, (o1,o2) -> o2 - o1)
return integers[0]
})
System.out.println(maxInteger)
}
public static Integer getMaxInteger(Supplier<Integer> supplier) {
return supplier.get()
}
Consumer
public static void main(String[] args) {
setString("xiaoming", str -> {
System.out.println(str);
System.out.println(new StringBuffer(str).reverse());
});
}
public static void setString(String str, Consumer<String> consumer) {
consumer.accept(str);
}
andThen默认方法,如果参数是两个Consumer类型,就可以实现先做一个处理,再做下一个处理,谁写前面谁先消费
- 消费的都是输入的初始字符串,第二步处理的并不是第一步的结果
public static void main(String[] args) {
andThenConsumer("xiaoming,xiaozhang,xiaochen", s -> {
String[] split = s.split(",");
s += split[0];
System.out.println(s);
}, s -> {
System.out.println(s.toUpperCase());
});
}
public static void andThenConsumer(String str, Consumer<String> consumer1 , Consumer<String> consumer2) {
consumer1.andThen(consumer2).accept(str);
}
Predicate
- 对某个数据类型进行判断,返回
boolean值
test方法决定判断的方式
public static void main(String[] args) {
boolean res = test("java", s -> "java".equals(s));
System.out.println(res);
}
public static boolean test(String str, Predicate<String> predicate) {
return predicate.test(str);
}
and默认方法,类似&&,表示并且关系,连接两个判断条件
public static void main(String[] args) {
boolean andTestRes = andTest("jwewq", s -> s.length() > 2, s -> s.contains("a"));
System.out.println(andTestRes);
}
public static boolean andTest(String str, Predicate<String> predicate, Predicate<String> predicate2) {
return predicate.and(predicate2).test(str);
}
public static void main(String[] args) {
boolean orTestRes = orTest("jwewq", s -> s.length() > 2, s -> s.contains("a"));
System.out.println(orTestRes);
}
public static boolean orTest(String str, Predicate<String> predicate, Predicate<String> predicate2) {
return predicate.or(predicate2).test(str);
}
public static void main(String[] args) {
boolean negateTestRes = negateTest("java", s -> "java".equals(s));
System.out.println(negateTestRes);
}
public static boolean negateTest(String str, Predicate<String> predicate) {
return predicate.negate().test(str);
}
Function
public static void main(String[] args) {
functionMethod("123",s -> Integer.valueOf(s));
}
private static void functionMethod(String str, Function<String, Integer> function) {
System.out.println(function.apply(str));
}
andThen默认方法,组合操作,参数会传递,前面传递后会给后面处理
public static void main(String[] args) {
functionAndThen("123", s -> Integer.valueOf(s) + 10, integer -> String.valueOf(integer));
}
private static void functionAndThen(String str, Function<String, Integer> function1, Function<Integer, String> function2) {
System.out.println(function1.andThen(function2).apply(str));;
}
public static void main(String[] args) {
handleAge("xiaoming-30", s -> s.split("-")[1], s -> Integer.parseInt(s), integer -> integer + 10);
}
private static void handleAge(String str, Function<String, String> function1, Function<String, Integer> function2, Function<Integer, Integer> function3) {
System.out.println(function1.andThen(function2).andThen(function3).apply(str));;
}
流
ArrayList<String> strings = new ArrayList<>();
strings.add("zhangsan");
strings.add("zhangsi");
strings.add("zhangwu");
strings.add("wangwu");
strings.add("zhaoliu");
strings.stream().filter(s -> s.startsWith("zhang")).filter(s -> s.length() == 7).forEach(s -> System.out.println(s));
- 流的数据来源,可以是集合也可以是数组,可以进行内部迭代
获取流
- Stream流属于管道流,只能被消费一次,第一个流使用完毕后,就转到下一个了,上一个已经被关闭,不能被调用
Set<String> set = map.keySet();
Stream<String> setStream = set.stream();
Stream<Integer> integerStream = Stream.of(312, 3213, 4214, 54);
终结方法
- 使用终结方法后,流就结束了
forEach里面放着Consumer接口,使用数据
count输出数量
- collect,将流转换为集合
ArrayList<String> strings = new ArrayList<>()
strings.add("123123")
strings.add("213123")
strings.add("1323123")
//直接转换成集合
List<Integer> collect = strings.stream().map(s -> Integer.parseInt(s)).collect(Collectors.toList())
//新建,针对一个元素新建集合;累加,将一个元素添加到这个集合;合并每个元素的结合
ArrayList<Object> collect1 = strings.stream().map(s -> Integer.parseInt(s)).collect(ArrayList::new, ArrayList::add, ArrayList::addAll)
//没有值则为1或者0
Integer integer = collect.stream().max(Integer::compare).orElse(1);
Integer integer1 = collect.stream().min(Integer::compare).orElse(0);
过滤方法
Map<String, String> map = new HashMap<>();
map.put("zhangsan", "12");
map.put("zhang", "12");
map.put("zhasan", "32");
Stream<Map.Entry<String, String>> stream = map.entrySet().stream();
Stream<Map.Entry<String, String>> entryStream = stream.filter(stringStringEntry -> Integer.parseInt(stringStringEntry.getValue()) < 14);
entryStream.forEach(stringStringEntry -> System.out.println(stringStringEntry.getKey() + " - " + stringStringEntry.getValue()));
映射
map
- 将流中的数据映射到另一个流中,且可以改变数据类型
List<String> list = new ArrayList<>();
list.add("131");
list.add("3123");
list.add("12311");
list.stream().map(s -> Integer.parseInt(s)).forEach(integer -> System.out.println(integer + 1000));
取用前几个
list.stream().limit(7).forEach(s -> System.out.println(s));
跳过前几个
list.stream().skip(3).forEach(s -> System.out.println(s));
去重和合并
- 将一个集合的多个流,合并成一个流
flatMap 合并,扁平化处理
distinct 去重
pointsList.stream().flatMap(Collection::stream).distinct().sorted().collect(toList());
组合
- 静态方法
concat
- 数据类型可以不一样,但是要看具体怎么处理
Stream.concat(integer, list.stream()).forEach(s -> System.out.println(s));
方法引用
- 对
Lambda的简化
- 前提,
Lambda的方法体中使用的对象和方法是存在的
public static void main(String[] args) {
printString(s -> System.out.println(s));
printString(System.out::println);
}
private static void printString(Printable printable) {
printable.print("hello");
}
::引用运算符,Lambda传递的参数,一定要是引用方法中能接受的参数
自定义对象方法实现方法引用
public class MethodRefObject {
public void printUpperCaseString(String str) {
System.out.println(str.toUpperCase());
}
}
- 调用,
对象名和成员方法都已经存在,针对Lambda方法体的优化
public static void main(String[] args) {
printString(new MethodRefObject()::printUpperCaseString);
}
private static void printString(Printable printable) {
printable.print("hello");
}
通过类名实现方法引用
public static void main(String[] args) {
int abs = abs(-10, Math::abs);
int abs1 = abs(-20, number -> Math.abs(number));
System.out.println(abs);
System.out.println(abs1);
}
private static int abs(int number, Calcable calcable) {
return calcable.calsAbs(number);
}
子父类引用
public void method(Greetable greetable) {
greetable.greet();
}
public void show() {
method(super::hello);
method(this::hello);
}
类的构造引用
public static void main(String[] args) {
creatMan("zhangsan", name -> new Man(name));
creatMan("lisi", Man::new);
}
public static void creatMan(String name, ManBuilder manBuilder) {
System.out.println(manBuilder.builderMan(name).getName());
}
数据的构造引用
public static void main(String[] args) {
int[] ints = creatArrary(10, int[]::new);
System.out.println(ints.length);
}
public static int[] creatArrary(int length, ArraryBuilder arraryBuilder) {
return arraryBuilder.builderArrary(length);
}