黑马程序员技术交流社区

标题: 学习笔记 [打印本页]

作者: 沃土乐也强了    时间: 2018-12-2 16:27
标题: 学习笔记
day11
网络编程基础
C/S结构:
        全称为Client/Server结构, 是指 客户端 和 服务器 结构
        常见程序有QQ, 迅雷等软件
B/S结构:
        全称为Browser/Server结构, 是指 浏览器 和 服务器 结构
        常见浏览器有IE, 谷歌, 火狐等
网络通信协议
网络通信协议:
        通信协议是计算机必须遵守的规则, 只有遵守这些规则, 计算机之间才能进行通信.
        协议中对数据的传输格式, 传输速率, 传输步骤等做了统一规定, 通信双方必须同时遵守, 最终完成数据交换
UDP: User Datagram Protocol, 用户数据报协议
        特点:
                1. 无连接的不可靠协议
                2. 数据按包发送, 64K一个包
                3. 速度快效率高, 容易丢包
        用于视频直播, 网络电话

TCP: Transmission Control Protocol, 传输控制协议
        特点:
                1. 需要建立连接的可靠协议  电话
                2. 数据传输无大小限制
                3. 速度慢效率低   重发机制
        用于文件下载, 浏览网页

网络编程三要素: IP地址
网络编程三要素:
        1. 通信协议  TCP
        2. IP地址
        3. 端口号
网络三要素: 端口号
端口号: 计算机中进程的唯一标识
        端口号的取值范围: 0~65535的整数, 其中0~1024不建议使用
TCP通信
java.net.ServerSocket类: TCP服务端
        // 构造方法
        ServerSocket(int port): 创建一个TCP服务端, 并监听指定端口
        // 成员方法
        Socket accept(): 监听数据, 会阻塞. 收到数据后返回Socket对象
        void close(): 关闭服务端ServerSocket
java.net.Socket类: TCP客户端
        // 构造方法
        Socket(String ip, int port): 创建TCP客户端对象
        // 成员方法
        OutputStream getOutputStream(): 获取输出流对象, 用于发送数据
        InputStream getInputStream(): 获取输入流, 用于接收数据
        void shutdownOutput(): 关闭输出流, 发送结束标记
        void close(): 关闭客户端Socket
TCP程序: 客户端代码实现
java.net.Socket类: TCP客户端
        // 构造方法
        Socket(String 服务端ip, int 服务端port): 创建TCP客户端对象, 同时尝试连接到指定的服务端
                (客户端也会获取系统随机分配的一个端口号)
        // 成员方法
        OutputStream getOutputStream(): 获取输出流对象, 用于发送数据
        InputStream getInputStream(): 获取输入流, 用于接收数据
        void shutdownOutput(): 关闭输出流, 告知服务端数据发送完毕, 结束标记-1
        void close(): 关闭客户端Socket, 告知服务端数据发送完毕
实现步骤:
        1.创建一个客户端对象 Socket, 构造方法传入服务器的IP地址和端口号
        2.使用Socket对象中的方法 getOutputStream() 获取网络字节输出流OutputStream对象
        3.使用网络字节输出流OutputStream对象中的方法 write(), 给服务器发送数据
        4.使用Socket对象中的方法 getInputStream() 获取网络字节输入流InputStream对象
        5.使用网络字节输入流InputStream对象中的方法 read(), 读取服务器回写的数据
        6.释放资源(Socket)
注意:
        1.客户端和服务器端进行交互, 必须使用Socket中提供的网络流, 不能使用自己创建的流对象
        2.当我们创建客户端对象Socket的时候, 就会去请求服务器和服务器经过3次握手建立连接通路
                这时如果服务器没有启动, 那么就会抛出异常ConnectException: Connection refused: connect
                如果服务器已经启动, 那么就可以进行交互了
        // 创建客户端Socket对象, 指定要连接的服务端的IP和端口号
        Socket socket = new Socket("127.0.0.1", 8888);
        // 向服务端发送数据
        OutputStream os = socket.getOutputStream();
        os.write("你好服务器".getBytes());
        // 释放资源
        socket.close();
TCP程序: 服务器端代码实现
java.net.ServerSocket类: TCP服务端
        // 构造方法
        ServerSocket(int 服务端自己用的port): 创建一个TCP服务端, 并监听指定端口
        // 成员方法
        Socket accept(): 等待客户端连接, 会阻塞. 客户端连接后返回客户端的Socket对象
        void close(): 关闭服务端ServerSocket, 断开所有流
服务器的实现步骤:
        1.创建服务器ServerSocket对象并指定服务器占用的端口号
        2.使用ServerSocket对象中的方法 accept(), 获取到请求的客户端对象Socket
        3.使用Socket对象中的方法 getInputStream() 获取网络字节输入流InputStream对象
        4.使用网络字节输入流InputStream对象中的方法 read(), 读取客户端发送的数据
        5.使用Socket对象中的方法 getOutputStream() 获取网络字节输出流OutputStream对象
        6.使用网络字节输出流OutputStream对象中的方法 write(), 给客户端回写数据
        7.释放资源(Socket,ServerSocket)
        // 创建服务端ServerSocket对象, 并指定自己监听的端口
        ServerSocket server = new ServerSocket(8888);
        // 调用accept方法等待客户端连接
        Socket socket = server.accept();
        // 通过客户端获取输入流, 读取客户端发来的数据
        InputStream is = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int len = is.read(bytes);
        System.out.println(new String(bytes, 0, len));
        // 通过客户端获取输出流, 向客户端回写数据
        OutputStream os = socket.getOutputStream();
        os.write("收到谢谢".getBytes());
        // 释放资源
        socket.close();
        // server.close();  // 客户端一般不关闭
day12


函数式接口:是JDK1.8之后的新特性。特点是有且仅有一个抽象方法的接口。
在接口上使用@FunctionlInterface可以检查接口是不是函数式接口。
// 示例
@FunctionalInterface
public interface MyFunctionalInterface {
    void method();
}
函数式接口的使用
函数式接口有三种使用方式:
   作为方法的参数类型, 传递Lambda表达式, 代替匿名内部类方式
使用Lambda延迟执行可以优化代码:
     传递Lambda对象, 只有当符合执行条件时, 才会执行代码
常用函数式接口
Supplier生产型函数式接口

java.util.function.Supplier<T>函数式接口: 生产型函数式接口
        // 抽象方法
         T get(): 用于获取一个对象或值.
Consumer消费型函数式接口
java.util.function.Consumer<T>函数式接口: 消费型函数式接口
        // 默认方法
        default Consumer<T> andThen(Consumer<? super T> after): 拼接两个Consumer接口的Lambda对象实现连续操作. 谁写前面, 谁先消费

Predicate条件判断函数式接口
java.util.function.Predicate<T>函数式接口: 条件接口, 用于判断
        // 抽象方法
        boolean test(T t): 判断参数传递的对象. 至于怎么判断, 判断什么, 需要我们编写Lambda表达式实现
        // 默认方法 (用于连接多个判断条件)
        default Predicate<T> and(Predicate<? super T> other): 与 &&
        default Predicate<T> or(Predicate<? super T> other): 或  ||
        default Predicate<T> negate(): 非, 取相反结果   !

Function转换型函数式接口: 使用Function连续转换
[Java] 纯文本查看 复制代码
public class Test {
    // 方法作用: 按照步骤将字符串转换
    // 参数: 被转换的字符串, 转换方式1, 转换方式2, 转换方式3
    public static int change(String s, Function<String, String> fun1, Function<String, Integer> fun2, Function<Integer, Integer> fun3) {
        return fun1.andThen(fun2).andThen(fun3).apply(s);
    }

    public static void main(String[] args) {
        String str = "赵丽颖,20";

        // 匿名内部类方式
        int num1 = change(
                str,
                new Function<String, String>() {  // 将字符串截取数字年龄部分, 得到字符串
                    @Override
                    public String apply(String s) {
                        return s.split(",")[1];
                    }
                },
                new Function<String, Integer>() {  // 将上一步的字符串转换成为int类型的数字
                    @Override
                    public Integer apply(String s) {
                        return Integer.parseInt(s);
                    }
                },
                new Function<Integer, Integer>() { // 将上一步的int数字累加100, 得到结果int数字
                    @Override
                    public Integer apply(Integer integer) {
                        return integer + 100;
                    }
                }
        );
        System.out.println(num1);

        // Lambda方式
        int num2 = change(
                str,
                s -> s.split(",")[1],
                s -> Integer.parseInt(s),
                i -> i + 100
        );
        System.out.println(num2);
    }
}


Day13


Stream流
传统的过滤集合中的元素,很麻烦需要写很多的重复代码。在JDK8中出现了函数式变成思想。关注的是应该做什么,而不是怎样做。
流相比于集合的2个优点:
        1. Pipelining(管道特性): "可以链式调用"
                Stream流对象的 延迟方法 调用后, 会返回新的Stream流对象, 可以链式调用
                每个方法类似于一条一条的管道, 衔接了不同的处理方案
        2. 内部迭代特性: "不用写for循环"
                集合遍历通过 Iterator 或者 增强for, 显式的在集合外部进行迭代, 这叫做外部迭代
                Stream提供了内部迭代的方法 forEach(Consumer c), 可以直接调用遍历方法
使用Stream流的3个步骤:
        1. 获取数据源 (从"集合"或"数组"转换为"Stream"对象)
        2. 数据处理 (调用延迟方法, 编写处理方案)
        3. 获得结果 (调用终结方法, 启动开关)
有两种获取Stream流的方式:
获取Stream流对象的2种方式:
        1. 利用"Collection接口"中的默认方法 default Stream<E> stream() 方法: 集合转Stream对象
        2. 利用"Stream接口"中的静态方法 static <T> Stream<T> of(T... values): 数组转Stream对象

Stream API: 方法分类, forEach()遍历
Filter:
[Java] 纯文本查看 复制代码
package StreamFilterTest;

import java.util.stream.Stream;

public class StreamFilter {
    public static void main(String[] args) {
        String[] str= {"张三丰","张翠山","张无忌","赵敏","铁蛋"};
        Stream<String> str1 = Stream.of(str);
        Stream<String> str2 = str1.filter((String name) -> {
            return name.startsWith("张");
        });
        str2.forEach((String name)->{
            System.out.println(name);
        });
        Stream.of("张三丰","张翠山","张无忌","赵敏","铁蛋")
                .filter( name-> name.startsWith("张"))
                .forEach(name->System.out.println(name));
    }
}

map:
[Java] 纯文本查看 复制代码
package StreamMap;

import java.util.stream.Stream;

public class Test {
    public static void main(String[] args) {
        Stream<String> stream = Stream.of("1", "2", "3", "4", "5");
        Stream<Integer> stream1 = stream.map( i-> Integer.parseInt(i));
        stream1.forEach(integer->System.out.println(integer));
        Stream.of("1", "2", "3", "4", "5")
                .map(string->Integer.parseInt(string))
                .forEach(i-> System.out.println(i));
    }

}

limit:
[Java] 纯文本查看 复制代码
package StreamLimit;

import java.util.stream.Stream;

public class Test {
    public static void main(String[] args) {
        String[] str= {"铁锤","铁柱","铁球","铁饼","铁蛋"};
        Stream<String> str1 = Stream.of(str);
        Stream<String> limit = str1.limit(2);
        limit.forEach((String name)->{
            System.out.println(name);
        });

        System.out.println("*********");
        Stream.of("铁锤","铁蛋","铁柱")
                .limit(5)//limit(-1)   IllegalArgumentException: -1
                .forEach(name-> System.out.println(name));
        System.out.println("********");
        Stream.of("铁棒","铁球","铁柱")
                .limit(2)
                .skip(1)
                .forEach(name-> System.out.println(name));
    }
}


skip:
[Java] 纯文本查看 复制代码
package StreamSkip;

import java.util.stream.Stream;

public class Test {
    public static void main(String[] args) {
        String[] str= {"琦玉","银时","犬夜叉","三上悠雅","迪迦"};
        Stream<String> stream = Stream.of(str);
        Stream<String> stream1 = stream.skip(3);
        stream1.forEach(name-> System.out.println(name));
        System.out.println("*****************");
        Stream.of(str)
                .skip(4)
                .skip(-1)//返回 IllegalArgumentException: -1
                .skip(9)//返回一个空的流

                .forEach(name-> System.out.println(name));
    }
}












欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2