Day22-JDK8新特性

总结

我是最棒的!基础不牢,地动山摇!

缓冲流

为了达到高效的读写,使用缓冲流

BufferedInputStream

字节输入缓冲流,用法跟字节流类似

BufferedOutputStream

字节输出缓冲流,用法跟字节流类似

BufferedReader

字符输入缓冲流,用法跟字符流类似,不过多了readLine()读一行方法

BufferedWriter

字符输出缓冲流,用法跟字符流类似,多了newLine()方法

实例

package cn.itsource.study;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;

public class BufferStream2 {

	public static void main(String[] args) throws FileNotFoundException {
//		BufferedInputStream bis = new BufferedInputStream(new FileInputStream("test.txt"));
		try(BufferedReader br = new BufferedReader(new FileReader("test.txt"));
				BufferedWriter bw = new BufferedWriter(new FileWriter("test3.txt"))){
//			byte[] bs = new byte[1024];
//			int read  = -1;
//			while ((read = bis.read(bs)) != -1) {
//				bos.write(bs, 0, read);
//			}
			String readLine = null;
			while((readLine = br.readLine()) != null){
				bw.write(readLine);
				bw.newLine();
			}
			System.out.println("666");
			
		}catch (Exception e) {
			e.printStackTrace();
		}
	}

}

随机访问文件RandomAccessFile

可以用它来实现一些网络下载断点续传

RandomAccessFile构造方法

RandomAccessFile(File file, String mode)

RandomAccessFile(String name, String mode)

mode是指定模式 读r或者写w,读写rw

//一些重要方法
	//获得当前指针的位置
	long getFilePointer();
    //设置文件指针
	void seek(long pos)
    //返回此文件的长度
    long length()
    //设置此文件的长度
    void setLength(long newLength)
    

Java8新特性

· Lambda 表达式 − Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法中。

· 方法引用 − 方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。

· 默认方法 − 默认方法就是一个在接口里面有了一个实现的方法。

· 新工具 − 新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器jdeps。

· Stream API −新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。

· Date Time API − 加强对日期与时间的处理。

· Optional − Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。

函数式接口

函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。函数式接口可以被隐式转换为lambda表达式。

可以使用注解@FunctionalInterface标记该接口为函数式接口

我们在函数式接口上面加上此注解后,里面就只能够有一个抽象方法了,当然不加此注解且只有一个抽象方法的接口也是函数式接口,只是没有限定提示而已。

Lambda表达式

简单来看,可以说成是匿名内部类的缩写,使用Lambda表达式时,接口必须是函数式接口

基本语法

        <函数式接口>  <变量名> = (参数1,参数2...) -> {
                    //方法体
         }

特点说明:

(参数1,参数2…)表示参数列表;->表示连接符;{}内部是方法体
1、=右边的类型会根据左边的函数式接口类型自动推断;
2、如果形参列表为空,只需保留();
3、如果形参只有1个,()可以省略,只需要参数的名称即可;
4、如果执行语句只有1句,且无返回值,{}可以省略,若有返回值,则若想省去{},则必须同时省略return,且执行语句也保证只有1句;
5、形参列表的数据类型会自动推断;
6、lambda不会生成一个单独的内部类文件;
7、lambda表达式若访问了局部变量,则局部变量必须是final的,若是局部变量没有加final关键字,系统会自动添加,此后在修改该局部变量,会报错;

package cn.itsource.lambda;

@FunctionalInterface
public interface IMyInterface {
//	void test();
//	void test(int a);
//	void test(int a,int b);
   
//	int test();
//	int test(int a);
//	int test(int a,int b);
   User getUser(String name,int age,String sex);
}

class User{
   private String name;
   private int age;
   private String sex;
   
   public User() {
   }
   
   public User(String name, int age , String sex) {
   	this.name = name;
   	this.age = age;
   	this.sex = sex;
   }

   public String getName() {
   	return name;
   }

   public void setName(String name) {
   	this.name = name;
   }

   public int getAge() {
   	return age;
   }

   public void setAge(int age) {
   	this.age = age;
   }

   @Override
   public String toString() {
   	return "[" + name + ", " + age + ", " + sex + "]";
   }

}

测试类

package cn.itsource.lambda;

public class LambdaTest {

	public static void main(String[] args) {
//		IMyInterface iMyInterface = new IMyInterface() {
//			
//			@Override
//			public void test() {
//				System.out.println("wdnmd");
//			}
//		};
		
//		iMyInterface.test();
//		IMyInterface iMyInterface = () -> System.out.println("wdnmd");
//		iMyInterface.test();
		
//		IMyInterface iMyInterface = a -> System.out.println(a);
//		iMyInterface.test(1);
		
//		IMyInterface iMyInterface = (a,b) -> System.out.println(a+b);
//		iMyInterface.test(1, 2);
		
//		IMyInterface iMyInterface = () -> 0;
//		System.out.println(iMyInterface.test());
		
//		IMyInterface iMyInterface = a -> a;
//		System.out.println(iMyInterface.test(1));
		
//		IMyInterface iMyInterface = (a,b) -> a + b;
//		System.out.println(iMyInterface.test(2, 2));
		
//		IMyInterface iMyInterface = (a,b) -> {
//			int sum = a + b;
//			return sum;
//		};
//		
//		System.out.println(iMyInterface.test(2, 3));
		
//		IMyInterface iMyInterface = (name,age) -> new User(name, age);
//		System.out.println(iMyInterface.getUser("xxx", 18));
		
		IMyInterface iMyInterface = User :: new;
//		System.out.println(iMyInterface.getUser("xxx", 18));
		System.out.println(iMyInterface.getUser("xxx", 18,"女"));
		
		
		
	}

}

Stream

Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。

Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。

Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。

• 内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。

传入的类型和输出的类型一致,像一根管道一样,流式处理,一张图如下

[外链图片转存失败(img-NxcDN65s-1567172694824)(E:\ITSource\homework\0830Day22\resources\无标题.png)]

在 Java 8 中, 集合接口有两个方法来生成流:

stream() − 为集合创建串行流。

parallelStream() − 为集合创建并行流。

数据量大,业务多的时候选择使用并行流

数据量小,业务少的时候选择使用串行流

常用方法参见API

//map
//map 方法用于映射每个元素到对应的结果,以下代码片段使用 map 输出了元素对应的平方数:
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); 
// 获取对应的平方数 
List<Integer> squaresList = numbers.stream().
    map( i -> i*i).distinct().collect(Collectors.toList());

//filter
//filter 方法用于通过设置的条件过滤出元素。
//以下代码片段使用 filter 方法过滤出空字符串:
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); 
// 获取空字符串的数量 int count = strings.stream().filter(string -> string.isEmpty()).count();
________________________________________
//limit
//limit 方法用于获取指定数量的流。 以下代码片段使用 limit 方法打印出 10 条数据:
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);
________________________________________
//sorted
//sorted 方法用于对流进行排序。
//以下代码片段使用 sorted 方法对输出的 10 个随机数进行排序:
Random random = new Random(); 
random.ints().limit(10).sorted().forEach(System.out::println);
________________________________________
//并行(parallel)程序
//parallelStream 是流并行处理程序的代替方法。
//以下实例我们使用 parallelStream来输出空字符串的数量:
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); 
// 获取空字符串的数量 
int count = strings.parallelStream().filter(string -> string.isEmpty()).count();
//我们可以很容易的在顺序运行和并行直接切换。
________________________________________
//Collectors
//Collectors 类实现了很多归约操作,例如将流转换成集合和聚合元素。
//Collectors 可用于返回列表或字符串:
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); 
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList()); 
System.out.println("筛选列表: " + filtered); 
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", ")); 
System.out.println("合并字符串: " + mergedString);

Optional类

Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。

Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。

Optional 类的引入很好的解决空指针异常

善用Optional可以使我们代码中很多繁琐、丑陋的设计变得十分优雅。

实例

package cn.itsource.optional;

import java.util.Optional;
import java.util.function.Function;

/**
 *	Optional类测试 
 */
public class OptionalTest {

	public static void main(String[] args) {
		User u = null;
		System.out.println(getUserName(u));
		User u2 = new User("xxx");
		System.out.println(getUserName(u2));
	}

	public static String getUserName(User u){
		Optional<User> o = Optional.ofNullable(u);
		return o.map(new Function<User, String>() {

			@Override
			public String apply(User t) {
				return t.getName();
			}
		}).orElse("没有此用户");
		
		//Lambda表达式优化
//		return Optional.ofNullable(u).map(t -> t.getName()).orElse("没有此用户");
	}
	
}

class User{
	private String name;

	public User(String name) {
		super();
		this.name = name;
	}

	public User() {
		super();
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

日期时间API

Java 8通过发布新的Date-Time API (JSR 310)来进一步加强对日期与时间的处理。

在旧版的 Java 中,日期时间 API 存在诸多问题,其中有:

  1. 非线程安全 − java.util.Date 是非线程安全的,所有的日期类都是可变的,这是Java日期类最大的问题之一。

  2. 设计很差 − Java的日期/时间类的定义并不一致,在java.util和java.sql的包中都有日期类,此外用于格式化和解析的类在java.text包中定义。java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期,将其纳入java.sql包并不合理。另外这两个类都有相同的名字,这本身就是一个非常糟糕的设计。

  3. 时区处理麻烦 − 日期类并不提供国际化,没有时区支持,因此Java引入了java.util.Calendar和java.util.TimeZone类,但他们同样存在上述所有的问题

/*
LocalDate/LocalTime 和 LocalDateTime 
类可以在处理时区不是必须的情况。代码如下:
*/
// 获取当前的日期时间
LocalDateTime currentTime = LocalDateTime.now();
System.out.println("当前时间: " + currentTime); 
LocalDate date1 = currentTime.toLocalDate(); 
System.out.println("date1: " + date1); 
Month month = currentTime.getMonth();
int day = currentTime.getDayOfMonth();
int seconds = currentTime.getSecond();
System.out.println("月: " + month +", 日: " + day +", 秒: " + seconds);

//如果我们需要考虑到时区,就可以使用时区的日期时间API:
// 获取当前时间日期
ZonedDateTime date1 =ZonedDateTime.parse("2015-12-03T10:15:30+05:30[Asia/Shanghai]"); System.out.println("date1: " + date1);
ZoneId id = ZoneId.of("Europe/Paris"); 
System.out.println("ZoneId: " + id);
ZoneId currentZone = ZoneId.systemDefault(); 
System.out.println("当期时区: " + currentZone);


stem.out.println(“月: " + month +”, 日: " + day +", 秒: " + seconds);

//如果我们需要考虑到时区,就可以使用时区的日期时间API:
// 获取当前时间日期
ZonedDateTime date1 =ZonedDateTime.parse(“2015-12-03T10:15:30+05:30[Asia/Shanghai]”); System.out.println("date1: " + date1);
ZoneId id = ZoneId.of(“Europe/Paris”);
System.out.println("ZoneId: " + id);
ZoneId currentZone = ZoneId.systemDefault();
System.out.println("当期时区: " + currentZone);

猜你喜欢

转载自blog.csdn.net/t384061961/article/details/100166608