【JAVA8新特性】

(一)Lambda表达式

java8新特性支持lambda表达式,能让代码看起来更简洁。

interface Aaa{
public void printz(String z);
}

//老版本
    String t="gggg";
    Aaa olda=new Aaa() {

        @Override
        public void printz(String z) {
            // TODO Auto-generated method stub
            System.out.println(z);
        }
    };
    olda.printz(t);

    //JAVA 8
    //变量t在只后不得更改值,否则会报错,Local variable t defined in an enclosing
    //scope must be final or effectively final
    //lambda表达式内部只能调用final修饰的变量
    Aaa zAaa=((String z)->System.out.println(z+"qq"+t));
    zAaa.printz(t);

    //老版本
    Runnable oldrunnable=new Runnable() {

        @Override
        public void run() {
            // TODO Auto-generated method stub
            System.out.println("helloWorld");
        }
    };
    new Thread(oldrunnable).start();

    //java 8
    new Thread(()->System.out.print("helloWorld8")).start();

结果

(二)方法引用

      List<Name> names = new ArrayList<Name>();

      names.add(new Name("Bob"));
      names.add(new Name("JECK"));
      names.add(new Name("AICE"));
      names.add(new Name("SENCE"));
      names.add(new Name("MONTE"));



      names.forEach(Name::printz);
}

class Name{
    private String name;
    public Name(String name) {
        this.name=name;
    }

    public void printz() {
        System.out.println(name);
    }
}`

输出
Bob
JECK
AICE
SENCE
MONTE

(三)函数式接口

java8新提供了很多函数式接口,具体自行搜索,这里用其中一种做例子。

    public static void method1(List<Integer> list,Predicate<Integer> predicate) {
    for (Integer integer : list) {
        if(predicate.test(integer)) {
            System.out.print(integer+" ");
        }
    }
}
    List<Integer> nIntegers=Arrays.asList(1,2,3,4,5,6,7,8,9,10);
    //如何获取list里大于5的元素呢?

    //老方法
    for (Integer integer : nIntegers) {
        if(integer>5) {
            System.out.print(integer+" ");
        }
    }

    System.out.println();

    //运用java8提供的函数接口
    method1(nIntegers, n->n>5);

    System.out.println();

    //运用java8新特性省略方法,更简洁
    nIntegers.stream().filter(n->n>5).forEach(System.out::print);

结果

(四)默认方法

Java 8 新增了接口的默认方法。

简单说,默认方法就是接口可以有实现方法,而且不需要实现类去实现其方法。

我们只需在方法名前面加个default关键字即可实现默认方法
为了解决接口的修改与现有的实现不兼容的问题。

public class Java8Test {

@Test
public void test() {
    System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
    CarS car=new CarS();
    car.ss();

}

public interface Car{
default void haha() {
    System.out.println("haha");
}

}
public interface Bus{
default void haha() {
    System.out.println("heihei");
}
}
public class CarS implements Car,Bus{

public void ss() {
    haha();
}

@Override
public void haha() {
    // TODO Auto-generated method stub
    Bus.super.haha();
    Car.super.haha();
}
}

}

(五)Stream

java8引入一种新的抽象称做流Stream,能以声明的方式来处理数据。

下面代码实现了随机产生10个数,并把大于0的数输出。

Random random=new Random();
random.ints().limit(10).filter(n->n>0).forEach(System.out::println);

下面代码对list里的字符串重复拼接输出到5条记录的数组里,并输出数组。

List<String> sList=Arrays.asList("a","b","c","d","e","f","g");
System.out.println(sList.stream().map(n->n+n).limit(5).collect(Collectors.toList()));

另外,parallelStream()相对于stream(),是流并行处理方式。
统计结果的收集器

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);                 
IntSummaryStatistics  stats = numbers.stream().mapToInt((x) -> x).summaryStatistics(); 
System.out.println("列表中最大的数 : " + stats.getMax()); 
System.out.println("列表中最小的数 : " + stats.getMin()); 
System.out.println("所有数之和 : " + stats.getSum());
System.out.println("平均数 : " + stats.getAverage());

(六)Optional类

一个可以存放null的容器,解决了nullpoint空指针问题。

    Integer value1 = null;
Integer value2 = 222;
Optional<Integer> a = Optional.ofNullable(value1);

  // Optional.of - 如果传递的参数是 null,抛出异常 NullPointerException
Optional<Integer> b = Optional.of(value2);

System.out.println(a.orElse(555));
System.out.println(b.get());

输出555
222
其中a.orElse为如果为空值则取555,b若为空则抛出异常。

(七)Nashorn JavaScript

Nashorn 一个 javascript 引擎。

从JDK 1.8开始,Nashorn取代Rhino(JDK 1.6, JDK1.7)成为Java的嵌入式JavaScript引擎。Nashorn完全支持ECMAScript 5.1规范以及一些扩展。它使用基于JSR 292的新语言特性,其中包含在JDK 7中引入的 invokedynamic,将JavaScript编译成Java字节码。

与先前的Rhino实现相比,这带来了2到10倍的性能提升。

实现了java和JavaScript互相调用。

ScriptEngineManager  scriptEngineManager = new  ScriptEngineManager(); 
ScriptEngine  nashorn = scriptEngineManager.getEngineByName("nashorn"); 
String  name = "Runoob"; Integer  result = null; 
try  {  
nashorn.eval("print('" + name + "')");
 result = (Integer)  
 nashorn.eval("10 + 2"); 
 }catch(ScriptException  e){
   System.out.println("执行脚本错误: "+ e.getMessage()); 
   }  
   System.out.println(result.toString());

输出Runoob 12

var  BigDecimal  =  Java.type('java.math.BigDecimal'); 
function calculate(amount, percentage)  { 
var result =  new  BigDecimal(amount).multiply(  new  BigDecimal(percentage)).divide(new  BigDecimal("100"),  2,  BigDecimal.ROUND_HALF_EVEN);
return result.toPlainString();  }  
var result = calculate(568000000000000000023,13.9);  
print(result);

命令行运行上诉程序 : jjs xxx.js
结果:78952000000000002017.94

(八)日期时间API

旧版java中,日期时间相关的类存在诸多问题:非线程安全设计差(java.util和java.sql中日期类名相同,但对应内容不一致,前者多了具体时间)、时区处理麻烦

java8在java.time包里引入了很多新的API:local、 zoned….

    // 获取当前的日期时间
LocalDateTime currentTime = LocalDateTime.now();
System.out.println("LocalDateTime.now: " + currentTime);

LocalDate date1 = currentTime.toLocalDate();
System.out.println("localdatetime.tolocaldate=localdate: " + date1);

Month month = currentTime.getMonth();
int day = currentTime.getDayOfMonth();
int seconds = currentTime.getSecond();

System.out.println("localdatetime.getmonth=month: " + month +", localdatetime.getdayofmonth=int: " + day +", localdatetime.getseconds=int: " + seconds);

//用当前时间,修改天数和年份
LocalDateTime date2 = currentTime.withDayOfMonth(10).withYear(2012);
System.out.println("date2: " + date2);

//设置一个日期对象的值
LocalDate date3 = LocalDate.of(2014, Month.DECEMBER, 12);
System.out.println("date3: " + date3);

//设置时间的值
LocalTime date4 = LocalTime.of(22, 15);
System.out.println("date4: " + date4);

//用另一种格式设置时间
LocalTime date5 = LocalTime.parse("20:15:30");
System.out.println("date5: " + date5);

输出:LocalDateTime.now: 2018-10-13T20:14:29.390
localdatetime.tolocaldate=localdate: 2018-10-13
localdatetime.getmonth=month: OCTOBER, localdatetime.getdayofmonth=int: 13, localdatetime.getseconds=int: 29
date2: 2012-10-10T20:14:29.390
date3: 2014-12-12
date4: 22:15
date5: 20:15:30

时区相关:

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

ZonedDateTime dateTime=ZonedDateTime.now(currentZone);
System.out.println("当前时区时间:"+dateTime);

输出:
date1: 2015-12-03T10:15:30+08:00[Asia/Shanghai]
ZoneId: Europe/Paris
当期时区: Asia/Shanghai
当前时区时间:2018-10-13T20:20:45.466+08:00[Asia/Shanghai]


时间相关的计算:计算上个月的今天是周几?

LocalDateTime currentTime = LocalDateTime.now();
currentTime=currentTime.withMonth(currentTime.getMonthValue()-1);
System.out.println(currentTime.getDayOfWeek());

结果:THURSDAY

(九)Base64

Java 8 内置了 Base64 编码的编码器和解码器。

   try {

   // 使用基本编码
   String base64encodedString = Base64.getEncoder().encodeToString("runoob?java8".getBytes("utf-8"));
   System.out.println("Base64 比那么字符串 (基本) :" + base64encodedString);

   // 解码
   byte[] base64decodedBytes = Base64.getDecoder().decode(base64encodedString);

   System.out.println("原始字符串: " + new String(base64decodedBytes, "utf-8"));
   base64encodedString = Base64.getUrlEncoder().encodeToString("TutorialsPoint?java8".getBytes("utf-8"));
   System.out.println("Base64 编码字符串 (URL) :" + base64encodedString);

   StringBuilder stringBuilder = new StringBuilder();

   for (int i = 0; i < 10; ++i) {
      stringBuilder.append(UUID.randomUUID().toString());
   }

   byte[] mimeBytes = stringBuilder.toString().getBytes("utf-8");
   String mimeEncodedString = Base64.getMimeEncoder().encodeToString(mimeBytes);
   System.out.println("Base64 编码字符串 (MIME) :" + mimeEncodedString);
   byte[] aString=Base64.getMimeDecoder().decode(mimeEncodedString);
   String aString2=new String(aString,"utf-8");
   System.out.println(aString2);

}catch(UnsupportedEncodingException e){
   System.out.println("Error :" + e.getMessage());
}

结果:
Base64 比那么字符串 (基本) :cnVub29iP2phdmE4
原始字符串: runoob?java8
Base64 编码字符串 (URL) :VHV0b3JpYWxzUG9pbnQ_amF2YTg=
Base64 编码字符串 (MIME) :ZDEzM2E2MGEtNTllMS00ZGI5LWE5OWItNDFkNWMwZWU4ZWRlNzVkMmM5NTctMjFmNi00NTM3LWE2
NjQtMTUwNmJkOGU0ZWZjNDk0YjEyMTctM2RhZi00NDQ0LTgzNGItYzE0ZWFiY2ZhZWUxYzUxYjNj
N2MtMjQ0My00Y2UwLTlhZWItNjE0M2EzZDUzNmQ5OGNjMTgxZTgtMjg3MS00ZDY0LTg0MDktZTgw
MGE2OTNlZDdiM2QyOTBiNmQtYTUyYi00NzY3LWFjZmYtMWM0ODRiOGNmNGQzZjhkZjQ0MDItOWMw
Ni00YjMzLWEyZGUtZDcxYzc4N2NiZjBkMzQ2ZTY1OWQtMjU1OS00ZDVjLWE3ZjktMDQyMWNmYmY4
MjVlMmNhMDhkZGItMDU5OC00Yjk1LTg2ZjktNTdmYWRjZDBjMDBiOWYyYmMzYWMtZDAwNi00ZThk
LTlhNjQtNTU3OTcxODk1NjZi
d133a60a-59e1-4db9-a99b-41d5c0ee8ede75d2c957-21f6-4537-a664-1506bd8e4efc494b1217-3daf-4444-834b-c14eabcfaee1c51b3c7c-2443-4ce0-9aeb-6143a3d536d98cc181e8-2871-4d64-8409-e800a693ed7b3d290b6d-a52b-4767-acff-1c484b8cf4d3f8df4402-9c06-4b33-a2de-d71c787cbf0d346e659d-2559-4d5c-a7f9-0421cfbf825e2ca08ddb-0598-4b95-86f9-57fadcd0c00b9f2bc3ac-d006-4e8d-9a64-55797189566b


……

Over~