Java基础6

TCP通信:
通信步骤:服务器端先启动,服务器端不会主动请求客户端,必须使用客户端请求服务器端,两者之间就会建立一个逻辑连接,而这个连接包含一个IO对象,客户端和服务器端通过这个IO对象来进行通信,通信的数据不仅仅是字符,所以IO对象是一个字节流
在这里插入图片描述

package TCPDemo;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

/**
 * Socket:包含了IP地址和端口号的网络单位
 *
 * 构造方法:
 * Socket(String host,int port):创建一个流套接字并将其连接到指定主机上的指定端口号
 * 参数:
 * String host:服务器主机的名称/IP地址
 * int port:端口号
 * 成员方法:
 * OutputStream getOutputStream():返回套接字的输出流
 * InputStream getInputStream():返回套接字的输入流
 * void close()
 *
 * 实现步骤:
 * 1.创建一个客户端对象Socket,构造方法绑定服务器的IP地址和端口号
 * 2.使用Socket对象中的方法getOutputStream()获取网络字节输出流OutputStream对象
 * 3.使用网络字节输出流OutputStream对象中的方法write,给服务器发送数据
 * 4.使用Socket对象中的方法getInputStream()获取网络字节输入流InputStream对象
 * 5.使用网络字节输入流InputStream中的方法read读取服务器回写的数据
 * 6.释放资源(Socket)
 *
 * 注意事项:
 * 1.客户端和服务器进行交互,必须使用Socket中提供的网络流,不能使用自己创建的对象
 * 2.当我们创建客户端对象Socket的时候,就会去请求服务器和服务器建立连接
 */

public class TCPClientDemo {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1",8888);
        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();
    }
}

package TCPDemo;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * ServerSocket套接字:
 * 构造方法:
 * ServerSocket(int port):创建绑定到特定端口的服务器套接字
 * 服务器端必须知道是哪个客户端请求的服务器,所以可以使用accept方法请求获取到请求的客户端对象Socket
 *
 * 服务器实现步骤:
 * 1.创建服务器ServerSocket对象和系统要指定的端口号
 * 2.使用ServerSocket对象中的方法accept,获取到请求的客户端对象Socket
 * 3.使用Socket对象中的方法getInputStream()获取网络字节输入流InputStream对象
 * 4.使用网络字节输入流InputStream中的方法read读取服务器回写的数据
 * 5.使用Socket对象中的方法getOutputStream()获取网络字节输出流OutputStream对象
 * 6.使用网络字节输出流OutputStream对象中的方法write,给客户端发送数据
 * 7.释放资源
 */

public class TCPServerDemo {
    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(8888);
        Socket socket = server.accept();
        InputStream inputStream = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int len = inputStream.read(bytes);
        System.out.println(new String(bytes,0,len));

        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("收到谢谢".getBytes());
        socket.close();
        server.close();
    }
}

上传文件案例:
在这里插入图片描述
在这里插入图片描述
函数式编程:
函数式接口:有且只有一个抽象方法的接口(但是可以包含其它的方法:默认、静态、私有)

package LambdaDemo;

@FunctionalInterface    //检测是否是一个函数式接口
public interface MyFunctionalInterface {
    //定义一个抽象方法
    public abstract void method();
    //void method1();
}

package LambdaDemo;

public class MyFunctionalInterfaceImpl implements MyFunctionalInterface {

    @Override
    public void method() {

    }
}

package LambdaDemo;

/**
 * 函数式接口的使用:一般作为方法的参数和返回值类型
 */

public class Demo {
    //定义一个方法,参数使用函数式接口
    public static void show(MyFunctionalInterface myInter){
        myInter.method();
    }

    public static void main(String[] args) {
        //调用show方法,方法的参数是一个接口,可以传递接口的实现类对象
        show(new MyFunctionalInterfaceImpl());

        //调用show方法,方法的参数是一个接口,我们可以传递接口的匿名内部类
        show(new MyFunctionalInterface() {
            @Override
            public void method() {
                System.out.println("使用匿名内部类重写接口");
            }
        });

        //调用show方法,方法的参数是一个函数式接口,我们可以传递Lambda表达式
        show(
                ()->{
                    System.out.println("使用Lambda重写接口中的抽象方法");
                }
        );
    }
}

Lambda表达式可以延时调用案例:

package LambdaDemo;

@FunctionalInterface
public interface MessageBuilder {
    //定义一个拼接消息的抽象方法,返回被拼接的字符串
    public abstract String builderMessage();
}

package LambdaDemo;

/**
 * 使用Lambda优化日志案例
 * Lambda的特点:延迟加载
 * Lambda的使用前提,必须存在函数式接口
 */

public class LambdaDemo2 {
    public static void main(String[] args) {
        String msg1 = "hello";
        String msg2 = "world";
        String msg3 = "Java";

        //参数MessageBuilder是一个函数式接口,所以可以传递Lambda表达式
        showLog(1,()->{
            //返回一个拼接好的字符串
            return msg1+msg2+msg3;
        });
        /**
         * 使用Lambda表达式作为参数传递,仅仅是把参数传递到showLog方法中
         * 只有满足条件,日志等级是1,才会调用接口MessageBuilder中的方法builderMessage
         * 才会进行字符串的拼接
         * 如果条件不满足,日志等级不是1级,那么MessageBuilder接口中的方法builderMessage也不会执行
         * 所以拼接字符串的代码也不会执行,不会存在性能的浪费
         */
    }

    //定义一个现实日志的方法,方法的参数传递日志的等级和MessageBuilder接口
    public static void showLog(int level,MessageBuilder mb){
        //对日志的等级进行判断,如果是1级,则调用MessageBuilder接口中的BuilderMessage方法
        if(level==1){
            System.out.println(mb.builderMessage());
        }

    }

}

函数式接口作为方法的返回值:

package LambdaDemo;

import java.util.Arrays;
import java.util.Comparator;

/**
 * 如果一个方法的返回值类型是一个函数式接口,那么就可以返回一个Lambda表达式
 * 当需要通过一个方法来获取java.util.Comparator接口类型的对象作为排序时,就可以调用该方法获取
 */

public class ComparatorDemo {
    //定义一个方法,方法的返回值类型使用函数式接口
    /*public static Comparator<String> getComparator(){
        //方法的返回值类型是一个接口,那么我们可以返回这个接口的匿名内部类
        return new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                //按照字符串的降序排序
                return o2.length()-o1.length();
            }
        };
    }*/
    //方法的返回值类型是一个接口,那么我们可以返回一个Lambda表达式
    public static Comparator<String> getComparator() {
        return (String o1, String o2)->{
                //按照字符串的降序排序
                return o2.length() - o1.length();
            };
    }

    public static void main(String[] args) {
        String[] arr = {"aaa","bb","ccccccccc","ddddddddddddddddd"};
        Arrays.sort(arr,getComparator());
        System.out.println(Arrays.toString(arr));
    }

}

常用的函数式接口:
Supplier接口:

package LambdaDemo;

import java.util.function.Supplier;

/**
 * 常用的函数式接口:Supplier
 * Supplier<T>  接口被称之为生产型接口,指定接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据
 */

public class SupplierDemo {

    //定义一个方法,方法的参数传递Supplier<T>接口,泛型执行String,get方法就会返回一个字符串
    public static String getString(Supplier<String> supplier){
        return supplier.get();
    }

    public static void main(String[] args) {
        String str = getString(()->{
            return "胡歌";
        });
        System.out.println(str);
    }

}

Consumer接口:

package LambdaDemo;

import java.util.function.Consumer;

/**
 * Consumer<T>接口与Supplier接口相反,它不是生产一个数据,而是消费一个数据,其数据类型由泛型决定
 * Consumer接口中包含抽象方法void accept(T,t),意为消费一个数据
 *
 * Consumer接口的的默认方法:andThen
 * 作用:需要两个Consumer接口,可以把两个Consumer接口组合到一起,再对数据进行消费
 *
 * 比如:
 * Consumer<String> con1
 * Consumer<String> con2
 * String str="hello";
 * con1.accept(str);
 * con2.accept(str);
 * 等价于:con1.andThen(con2).accept(str);谁写前面,谁先消费
 */

public class ConsumerDemo {

    public static void method(String name, Consumer<String> con){
        con.accept(name);
    }

    public static void method2(String s,Consumer<String> con1,Consumer<String> con2){
        /*con1.accept(s);
        con2.accept(s);*/
        con1.andThen(con2).accept(s);
    }

    public static void main(String[] args) {
        method("赵丽颖",(String name)->{
           //对传递的字符串进行消费
            System.out.println(name);
        });

        method2("AAAbbb",
                (String name)->{
                    System.out.println(name.toUpperCase());
                },
                (String name)->{
                    System.out.println(name.toLowerCase());
                });
    }

}

Predicate接口:

package LambdaDemo;

import java.util.function.Predicate;

/**
 * java.util.function.Predicate<T>接口
 * 作用:对某种数据类型的数据进行判断,返回布尔值
 * Predicate接口中包含一个抽象方法:boolean test(T t):用来对指定的数据类型进行判断的方法
 * 结果:符合条件,返回true
 *      不符合条件,返回false
 *
 *
 */

public class PredicateDemo {

    /**
     * 定义一个方法
     * 参数传递一个String类型的字符串
     * 传递一个Predicate接口,泛型使用String
     * 使用Predicate中的方法test对字符串进行判断,并把判断结果进行返回
     */

    public static boolean checkString(String s, Predicate<String> pre){
        return pre.test(s);
    }

    /**
     *
     * @param s    传入的字符串
     * @param pre1   判断字符串长度是否大于5
     * @param pre2    判断字符串是否包含a
     * @return
     */
    public static boolean checkString2(String s,Predicate<String> pre1,Predicate<String> pre2){
        return pre1.and(pre2).test(s);
    }

    public static void main(String[] args) {
        boolean flag = checkString("abcd",(String str)->{
            //对参数传递的字符串进行判断,判断字符串的长度是否是大于5,并把判断结果返回
            return str.length()>5;
        });
        System.out.println(flag);
        System.out.println("==========================");

        boolean flag1 = checkString2("abcdef",
                (String str)->{
            return str.length()>5;
                },
                (String str)->{
            //boolean flag = false;
            return str.contains("a");
                });
        System.out.println(flag1);
    }

}

Function接口:

package LambdaDemo;

import java.util.function.Function;

/**
 * java.util.function.Function<T,R>接口用来根据一个类型的数据得到另一个类型的数据
 * 前者称为前置条件,后者称为后置条件
 * Function接口中最主要的抽象方法为:R apply(T t):根据类型T的参数获取类型R的结果
 * 使用的场景例如:将String类型转换为Integer类型
 */

public class FunctionDemo {
    /**
     *
     * @param s
     * @param fun  使用Function接口中的方法apply,把字符串类型的整数,转换为Integer类型的整数
     */
    public static void change(String s, Function<String,Integer> fun){
        Integer apply = fun.apply(s);
        System.out.println(apply);
    }

    public static void main(String[] args) {
        String s= "1234";
        change(s,(String str)->{
           return Integer.parseInt(str);
        });
    }

}

流式思想:
Stream流:
filter->map->skip->count
获取流:
两种方式:

package LambdaDemo;

import java.util.*;
import java.util.stream.Stream;

/**
 * 流的转换方式(2种):
 * stream():
 * of:
 */

public class StreamDemo2 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        Stream<String> stream = list.stream();

        Map<String,String> map = new HashMap<>();
        Collection<String> values = map.values();
        values.stream();

        Set<Map.Entry<String, String>> entries = map.entrySet();
        entries.stream();
        
        int[] arr = {1,2,3,4};
        Stream<int[]> arr1 = Stream.of(arr);
        
    }
}

Stream流中的长用方法:

package LambdaDemo;

import java.util.stream.Stream;

/**
 * void forEach(Consumer<? super T> action)
 * 该方法接收一个Consumer接口函数,会将每一个流元素交给该函数进行处理
 * Consumer接口是一个消费型的函数接口,可以传递Lambda表达式
 *
 * 简单记:
 * forEach(参数是Consumer接口)方法,用来遍历流中的数据,是一个终结方法,遍历之后不能继续调用Stream流中的其它方法
 *重写
 *
 * filter(参数是Predicate接口):
 * 重写boolean test(T t)抽象方法
 *
 */

public class StreamDemo3 {
    public static void main(String[] args) {
        Stream<String> stream = Stream.of("张三", "李四", "王五", "赵六", "田七");
        /*stream.forEach((String name)->{
            System.out.println(name);
        });*/

        stream.forEach(name->System.out.println(name));
        System.out.println("====================================");
        Stream<String> stream1 = Stream.of("张三丰", "张翠山", "赵敏", "周芷若", "张无忌");
        Stream<String> stream2 = stream1.filter((String name) -> {
            return name.startsWith("张");
        });
        stream2.forEach(name-> System.out.println(name));
        System.out.println("==================================");

        Stream<String> stringStream = Stream.of("1", "2", "3", "4");
        Stream<Integer> integerStream = stringStream.map((String s) -> {
            return Integer.parseInt(s);
        });
        integerStream.forEach(name-> System.out.println(name));
    }
}

方法引用:

package LambdaDemo;

@FunctionalInterface
public interface printable {
    public abstract void print(String s);
}

package LambdaDemo;

@FunctionalInterface
public interface Calcable {
    int calsAbs(int number);
}

package LambdaDemo;

public interface Greeable {
    void greet();
}

package LambdaDemo;

public class MethodRerObject {
    public void printUpperCaseString(String str){
        System.out.println(str.toUpperCase());
    }
}

package LambdaDemo;

public class Human {
    public void sayHello(){
        System.out.println("Hello");
    }
}

package LambdaDemo;

public class Man extends Human {
    @Override
    public void sayHello() {
        System.out.println("hello,I'am man");
    }

    public void method(Greeable g){
        g.greet();
    }

    public void show(){
        /*method(()->{
            Human h = new Human();
            h.sayHello();
        });*/
        method(super::sayHello);
    }

    public static void main(String[] args) {
        new Man().show();

    }
}

package LambdaDemo;

public class PrintDemo {
    public static void printString(printable pri){
        pri.print("Hello World");
    }

    public static void main(String[] args) {
        printString((s)->{
            System.out.println(s);
        });

        /**
         * 分析:Lambda表达式的目的,打印传递参数的字符串
         * 把参数s传递给了System.out对象,调用out对象中的方法prinln对字符串进行了输出
         * 注意:
         * 1.System.out对象已经存在
         * 2.println方法也是已经存在的
         * 所以可以使用方法引用来优化Lambda表达式
         */

        printString(System.out::println);


        System.out.println("==============================");

        /**
         * 通过对象名引用成员方法
         * 前提:对象名已经存在,成员方法也已经存在,就可以使用对象名来引用成员方法
         */
        printString1((String s)->{
            MethodRerObject obj = new MethodRerObject();
            obj.printUpperCaseString(s);
        });

        MethodRerObject obj = new MethodRerObject();
        printString1(obj::printUpperCaseString);
        System.out.println("================================");

        /**
         * 通过类名引用静态方法
         *
         */
        int num = method(-10,(n)->{
            return Math.abs(n);
        });
        System.out.println(num);

        int num2 = method(-10, Math::abs);
        System.out.println(num2);


    }

    public static void printString1(printable p){
        p.print("hello");
    }

    public static int method(int number,Calcable c){
        return c.calsAbs(number);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值