zoukankan      html  css  js  c++  java
  • java学习笔记(七)---网络编程以及java8新特性

    1、IP地址的操作类

    public class Test {
        public static void main(String[] args) {
            try {
                //获取本地的主机名
                System.out.println(InetAddress.getLocalHost());
                //根据主机名或IP获取对应的信息
                System.out.println(InetAddress.getByName("LAPTOP-QJ8392HF"));
                System.out.println(InetAddress.getByName("192.168.31.42"));
                System.out.println(InetAddress.getByName("www.baidu.com"));
                //获取所有的IP地址的信息
                for(InetAddress item: InetAddress.getAllByName("LAPTOP-QJ8392HF")) {
                    System.out.println(item);
                }
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
    
        }
    }

    2、传输协议

      UDP: 相当于发短信(有字数限制)

          不需要建立连接

           数据报的大小限制在64K内

          效率高,不安全,容易丢包

      TCP: 相当于打电话,需要建立连接

          效率相对比较低,数据传输安全

          三次握手完成

         (点名 ---> 答到 ---> 确认)

     3、居于TCP协议的socket网络编程

        --进行网络编程时,Socket需要借助数据流来完成数据的传递工作

     入门案例

      ---socket服务端

    public class Service {
        public static void main(String[] args) throws IOException {
            ServerSocket serverSocket = new ServerSocket(1080);
            Socket accept = serverSocket.accept();
            //输入流
            DataInputStream dataInputStream = new DataInputStream(accept.getInputStream());
            System.out.println(dataInputStream.readUTF());
            //输出流
            DataOutputStream dataOutputStream = new DataOutputStream(accept.getOutputStream());
            dataOutputStream.writeUTF("这个是我的回复,你可以收得到么?");
            dataInputStream.close();
            dataOutputStream.close();
            serverSocket.close();
        }
    }

      ---socket客户端

    public class Client {
        public static void main(String[] args) throws IOException {
            Socket socket = new Socket("127.0.0.1", 1080);
            //客户端的输出流
            DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
            dataOutputStream.writeUTF("这个是我发送的一条信息,你会回我的信息么?");
            //客户端的输入流
            DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
            System.out.println(dataInputStream.readUTF());
    
            dataOutputStream.close();
            socket.close();
        }
    }

     4、用socket传输文件

       ---服务端

    public class SocketService {
        public static void main(String[] args) throws IOException {
            ServerSocket serverSocket = new ServerSocket(10086);
            Socket accept = serverSocket.accept();
            InputStream inputStream = accept.getInputStream();
            FileOutputStream fileOutputStream = new FileOutputStream("yftest/test.jpg");
            byte[] arr = new byte[1024];
            while(inputStream.read(arr) != -1) {
                fileOutputStream.write(arr);
            }
            fileOutputStream.flush();
            accept.shutdownInput();
            fileOutputStream.close();
            inputStream.close();
            accept.close();
            serverSocket.close();
        }
    }

      ---客户端

    public class Client {
        public static void main(String[] args) throws IOException {
            Socket socket = new Socket("127.0.0.1", 10086);
            OutputStream outputStream = socket.getOutputStream();
            FileInputStream imageFile = new FileInputStream(Paths.get("C:", "Users/bill/Desktop/abc.jpg").toFile());
            byte[] buffer = new byte[1024];
            while(imageFile.read(buffer) != -1) {
                outputStream.write(buffer);
            }
            outputStream.flush();
            socket.shutdownOutput();
            imageFile.close();
            outputStream.close();
            socket.close();
        }
    }

    注意:通常来讲,服务端的socket服务会运行到accept那边,当如果没有接收到对应的流,那么代码是不会往下走的,当接收到一定的流后,代码才会往下走,所以不存在说运行服务端的代码后,就关闭了

     5、java8新特性

      ---lambda表达式

         lambda表达式是java8中最重要的新功能之一,使用lambda表达式可以替代只有一个抽象的接口实现,告别匿名内部类,代码看起来更简洁易懂。lambda表达式同时还提升了对集合、框架的迭代,遍历,过滤数据的操作

      特点:

        1、函数式编程

        2、参数类型自动推断

        3、代码量少,简洁

    public class Test {
        public static void main(String[] args) {
            //方式一
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("this is test");
                }
            });
            thread.start();
            //方式二 lambda表达式方式
            Thread thread2 = new Thread(() -> System.out.println("this is test"));
            thread2.start();
        }
    }

     案例二

    public interface ICompare {
        public boolean compare(Integer item);
    }
    public class Test {
        public static void main(String[] args) {
            ArrayList<Integer> arrayList = new ArrayList<>();
            Collections.addAll(arrayList, 1, 3, 5, 7, 6, 9, 8);
    
            Test.filterElement(arrayList, (Integer item) -> item > 5);
            Test.filterElement(arrayList, (Integer item) -> item > 8);
        }
    
        public static void filterElement(ArrayList<Integer> list, ICompare compare) {
            ArrayList<Integer> arr = new ArrayList<>();
            for(Integer item: list) {
                if(compare.compare(item)) {
                    arr.add(item);
                }
            }
            System.out.println(arr);
        }
    }
    public class Test {
        public static void main(String[] args) {
            Runnable runnable = () -> System.out.println("this is test");
            Runnable runnable1 = () -> {
                System.out.println("test 1");
            };
        }
    }

       ---Function接口的使用

    public class Test {
        public static void main(String[] args) {
            Function<String, Integer> func = (String name) -> name.length();
            System.out.println(func.apply("bill"));
        }
    }

         ---BiFunction接口的用法

    public class Test {
        public static void main(String[] args) {
            BiFunction<String, Integer, String> biFunction = (String name, Integer age) -> "名字:" + name + ", 年龄:" + age;
            String res = biFunction.apply("abc", 23);
            System.out.println(res);
        }
    }

      ---Supplier的用法

    Supplier<String> sup = () -> "bill gates";
    System.out.println(sup.get());

       ---Consumer的用法

    Consumer<String> consumer = System.out::println;
    consumer.accept("god");

       ---BiConsumer的用法

    public class Test {
        public static void main(String[] args) {
            BiConsumer<String, Integer> biConsumer = (String name, Integer age) -> System.out.println("名字:" + name + ",年龄:" + age);
            biConsumer.accept("test", 20);
        }
    }

    注意:类以上面的接口,用lambda表达式来实现,相当于在声明的时候,就声明好对应的方法,下面是调用,好比consumer在定义的时候,其实就定义了accept的方法,下面是accept方法的调用

       ---方法引用

       方法引用分:静态方法引用,实例方法引用,对象方法引用,构造方法引用

      

       ---静态方法引用与实例方法引用

    public class Test {
        public static void main(String[] args) {
         //静态方法引用
    //相当于方法Function<String, String> check = (String name) -> Func.funcTest(name); Function<String, String> check = Func::funcTest; System.out.println(check.apply("bill"));
         //实例方法引用
    //相当于方法Function<String, String> check2 = (String say) -> new Func().funcTest1(say); Function<String, String> check2 = new Func()::funcTest1; System.out.println(check2.apply("today is good day")); } } class Func { public static String funcTest(String name) { return "my name is " + name; } public String funcTest1(String say) { return "hello are you ok???" + say; } }

       ---构造方法类的引用

    public class Test {
        public static void main(String[] args) {
            BiFunction<String, Integer, Person> aNew = Person::new;
            Person bill = aNew.apply("bill", 20);
            System.out.println(bill.getDetail());
    
        }
    
    
    }
    
    class Person {
        private final String name;
        private final int age;
        public Person (String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public String getDetail () {
            return "名字:" + this.name + ", 年龄:" + this.age;
        }
    }

    注意:构造方法的引用,主要用于java的函数式编程,所以需要掌握Function, BigFunction, Supplier, Consumer, BigConsumer的使用

      ---Stream api及自定义注解

          steam是一组用来处理数组,集合的api

        java8之的以导入函数式编程的原因有:

          函数编程写出的代码简洁,且意图明了, 使用stream接口让你从此告别for循环

          多核友好,java函数式编程使用得编写并行程序从未如此简单,你需要的全部就是调用一下parallel()方法

         stream特性

          1、不是数据结构, 没有内部存储

          2、不支持索引访问

          3、延迟计算

          4、支持并行

          5、很容易生成数组以及集合(List,Set)

          6、支持过滤, 查找,转换,汇总,聚合等操作

        stream的创建(五种方式)---创建操作

    public class Test {
        public static void main(String[] args) {
            //方式一  通过数组的方式创建
            String[] strArr = new String[]{"a", "b", "c", "d", "e"};
            Stream<String> str = Stream.of(strArr);
            str.forEach(System.out::println);
    
            //方式二  通过集合的方式创建
            ArrayList<Integer> arrayList = new ArrayList<>();
            Collections.addAll(arrayList, 1, 2, 3, 4, 5, 6);
            arrayList.stream().forEach(System.out::println);
    
    
            //方式三 通过Stream.generate方法来创建, 注意:这里需要用limit来限制长度否则会无限的循环下去
            AtomicInteger num = new AtomicInteger(0);
            Stream<Integer> generate = Stream.generate(num::incrementAndGet);
            generate.limit(10).forEach(System.out::println);
            
            //方式四 通过Stream.iterate方法来创建
            Stream<Integer> iterate = Stream.iterate(1, val -> val + 1);
            iterate.limit(10).forEach(System.out::println);
    
            //方式五 通过其他方式来创建
            String string = "abcdefg";
            IntStream chars = string.chars();
            chars.forEach(System.out::println);
        }
    }

         stream的中间操作  ---中间操作

    public class Test {
        public static void main(String[] args) {
            ArrayList<Integer> integers = new ArrayList<>();
            Collections.addAll(integers, 1, 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 6);
            int sum = integers.stream().mapToInt(val -> val).sum();    //求和
    
            Integer integer = integers.stream().max((a, b) -> a - b).get();  //求最大值
            System.out.println(integer);
    
            Integer integer1 = integers.stream().min((a, b) -> a - b).get(); //求最小值
            System.out.println(integer1);
    
            //注意:如下方法,如果没有取结果的时候,程序是不会运行的,只有在需要取结果的时候,程序才会运行,
            //因为stream是没有存储空间的,所以这样是会节省很多IO空间
    
            Optional<Integer> any = integers.stream().filter(val -> val > 5).findAny();
            System.out.println(any.get());
    
            Optional<Integer> first = integers.stream().filter(val -> val > 5).findFirst();
            System.out.println(first.get());
    
            //进行排序,并转换成集合操作
            List<Integer> collect = integers.stream().sorted((a, b) -> a - b).collect(Collectors.toList());
            System.out.println(collect);
            System.out.println("------------------------");
            //去重
            List<Integer> collect1 = integers.stream().distinct().collect(Collectors.toList());
            System.out.println(collect1);
            //也可以通过转成set的方式去重
            Set<Integer> collect2 = integers.stream().collect(Collectors.toSet());
            //上面写法也可以写成
    //        Set<Integer> collect2 = new HashSet<>(integers);
            System.out.println(collect2);
        }
    }
    Stream.iterate(1, x -> x + 1).skip(20).limit(10).forEach(System.out::println);
    Stream.iterate(21, x -> x + 1).limit(10).forEach(System.out::println);
    //peek表示在运行过程中打印出每一项
    public class Test {
        public static void main(String[] args) {
            String str = "11,22,33,44,55";
            Stream<String> stream = Arrays.stream(str.split(","));
            int sum = stream.peek(System.out::println).mapToInt(Integer::valueOf).sum();
            System.out.println(sum);
        }
    }

    把字符串转成数组的灵活处理方式

    public class Test {
        public static void main(String[] args) {
            String str = "11,22,33,44,55";
            Stream<String> stream = Arrays.stream(str.split(","));
            IntStream intStream = stream.mapToInt(Integer::valueOf);
            System.out.println(intStream.sum());
        }
    }

     6、自定义注解

         Annontation是java5开始引入的新特征,中文名叫注解

        它提供一种安全的类似注释的机制,用来将任何的信息或元数据与程序元素(类, 方法,成员变量等)进行关联

        注释不会也不能影响代码的实际逻辑,仅仅起到辅助性作用。包含在java.lang.annotation包中

         @Override:定义在java.lang.Override中,此注释叧适用于修 饰方法,表示一个方法声明打算重写超类中的另一个方法声明 

         @Deprecated:定义在java.lang.Deprecated中,此注释可以 修饰方法、属性、类,表示不鼓励程序员使用这样的元素,通常 是因为它很危险戒者存在更好的选择

         @SuppressWarnings:定义在java.lang.SuppressWarnings中, 用来抑制编写编译时的警告信息 

         元注解的作用个是负责注解其他注解,java中定义了四个标准的 meta-annotation类型,他们被用来提供对其他annotation类型 作说明

         这些类型和它们所支持的类在java.lang.annotation包中

          – @Target:用来描述注解的使用范围(注解可以用在什么地方)

          – @Retention:表示需要在什么级别保存该注释信息,描述注解的生命周期 ▪ Source < Class < Runtime

          – @Document:说明该注解将被包含在javadoc中

          – @Inherited:说明子类可以继承父类中的该注解 

    自定义注解

    //注意:如果默认值是value那么就可以不用写
    @TestAnnotation(name="abc", age=12)
    public class MyAnnotation {
    }
    
    //用来声明当前自定义的注解适合用于什么地方,类,方法,变量,包。。。
    @Target({ElementType.TYPE, ElementType.METHOD})
    //retention用来表示当前注解适用于什么环境,是源码级别还是类级别还是运行环境,一般都是运行环境
    @Retention(RetentionPolicy.RUNTIME)
    //表示注解是否表示在javadoc中
    @Documented
    //表示当前注解是否能被继承
    @Inherited
    @interface TestAnnotation{
        //定义的方式看起来像方法,但是实际上使用在使用注解的时候填写的参数名称,默认注解是value
        //自定义注解中填写的所有方法都需要在使用注解的时候,添加值,很麻烦,因此可以包含默认值
        String name() default "bill";
        int age() default 1;
    }
  • 相关阅读:
    git和TortoiseGit安装
    poi导出excel
    POI生成word文档
    java反编译工具
    如何把wecenter的推荐的问题模块单独调取出来?
    想学网站运营?我教你啊!(下)
    想学网站运营?我教你啊!(中)
    想学网站运营?我教你啊!(上)
    织梦模块管理里面空白
    Discuz/X3.1去掉标题中的Powered by Discuz!以及解决首页标题后的"-"
  • 原文地址:https://www.cnblogs.com/rickyctbu/p/13510966.html
Copyright © 2011-2022 走看看