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