even

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

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;
}

 

posted on 2020-08-15 23:16  even_blogs  阅读(186)  评论(0编辑  收藏  举报