博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java 8
阅读量:4500 次
发布时间:2019-06-08

本文共 8893 字,大约阅读时间需要 29 分钟。

Java 8

Java8具有更快的运行速度,对底层的数据结构进行了修改,编程书写代码更少,提供了更加便利的Stream API,使用并行更简单,减少了空指针异常的产生,提供了一个容器类减少空指针异常。

Lambda 表达式

简介

一种匿名函数,类似一段可以传递的代码,将代码像传递数据一样在程序中进行传递。Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。

示例

public class Main {    public static  void main(String[] args) throws InterruptedException {      Runnable runnable = new Runnable() {          @Override          public void run() {              System.out.println("This is a inner class");          }      }; //匿名内部类               Thread thread = new Thread(runnable);        thread.start();        Runnable runnable_new = () -> System.out.println("This is a Lambda!");        Thread thread_new = new Thread(runnable_new);        thread_new.start();                System.out.println("------------------");    }}

语法

Lambda表达式中引入了 -> 操作符,箭头操作符的左侧对应参数列表,箭头右侧为需要执行的功能,需要“函数式接口”支持,即接口中只有一个抽象方法,可以使用@FuctionalInterface修饰,加强检查。

int i = 8;Runnable runnable = () -> System.out.println("This is implement" + i);@FunctionalInterfacepublic interface Test
{ public void method(); public void method(int i); public int method(int i,int j); public boolean method(int i,float j); public R method(T t1,T T2);}//仅作为举例 以下对每种情况具体进行了实现。Test test;//无参无返回值test = () -> System.out.println("This is implement");//单个参数无返回值test = (i) -> System.out.prinln("This is i" + i);test = x -> System.out.println("This is i" + i);//两个参数返回值Test test = (i,j) -> { System.out.prinln("This is i" + i); System.out.prinln("This is i" + j); return i+j;}//多个参数单条语句返回值Test test = (i,j) -> i+j;Teat test =(int i,float j) -> !(i+j);//泛型(i,j) -> i+j;

函数式接口

Lambda表达式需要依赖函数式接口,因此,Java8中内置了多种接口,简介四种核心函数式接口。

消费型接口

Consumer
void accept(T t);

提供型接口

Supplier
T get();

函数式接口

Function
R apply(T t);

判断型接口

Predicate
boolean test(T t);

其他接口

BiFunction
R apply(T t,U u);UnaryOperator
T apply(T t);BinaryOperator
T apply(T t1,T t2);ToIntFunction
ToLongFunction
ToDubleFunction
//返回int、long、doubleIntFunction
LongFunction
DoubleFunction
//返回R

示例

public void hello(String name,Consumer
consumer){ consumer.accept(name); }public String getDate(String data, Supplier
supplier){ return data +": "+ supplier.get(); }public String resoleString(String string, Function
function){ return function.apply(string); }public List
filterString(List
list,Predicate
predicate){ List
stringList= new ArrayList<>(); for (String string : list){ if(predicate.test(string)){ stringList.add(string); } } return stringList; } @Testpublic void test(){hello("Wang",(name) -> System.out.println("Hello ! I am " + name));/ String now = getDate("Now",() -> { Date d = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); return sdf.format(d); });System.out.println(now);/System.out.println("\tThis is a String with blank! ");String result = resoleString("\t\t\tThis is a String with blank! ", (string) -> string.trim());result = resoleString(result, (string) -> string.substring(5,20));System.out.println(result);/List
list = Arrays.asList("1234","abcd","http","a","Java and Oracle"); list = filterString(list,(s) -> s.length() > 5); for (String string : list) System.out.println(string);}

方法引用与构造器引用

Lambda 体中已经实现了的方法,可以进行使用,使用中只要遵循接口参数列表与构造或方法的参数返回值对应即可,带给你全新的体验。

使用方法

  • 对象 :: 实例方法名
  • 类 :: 静态方法名
  • 类 :: 实例方法名
Consumer
consumer = (x) -> System.out.println(x);Consumer
consumer = System.out::println;//实现方法的参数列表和引用方法必须保持一致Integer integer = new Integer(10);Supplier
supplier = integer::toString; Supplier
serviceSupplier= Executors::newCachedThreadPool;BiPredicate
predicate = String::equals; //等效于(x,y) -> x.equals(y);/* 哈哈哈 这还是Java吗? 哈哈哈*/ // a.method(b) 才可使用
  • 类名 :: new
Supplier
integer = Integer::new;//无参构造器Function
integer = Integer::new;//一个参数构造器//构造器的选择取决于Function中的方法参数,参数列表与构造器必须对应!
  • 类型 :: new
Function
function = (10) -> new String[x];Function
function = String[]::new;

Stream API

Stream 不是集合元素,它不是数据结构并不保存数据,它是有关算法和计算的,它更像一个高级版本Iterator。原始版本的Iterator,用户只能显式地一个一个遍历元素并对其执行某些操作;高级版本的 Stream,用户只要给出需要对其包含的元素执行什么操作,比如 “过滤掉长度大于 10的字符串”、“获取每个字符串的首字母”等,Stream 会隐式地在内部进行遍历,做出相应的数据转换,数据源本身可以是无限的。

图 1. 流管道的构成

获取方式

  • 从 Collection 和数组
    • Collection.stream()
    • Collection.parallelStream() 并行流!在执行迭代时是多线程完成的!
    • Arrays.stream(T array) or Stream.of()
  • 从 BufferedReader
    • java.io.BufferedReader.lines()
  • 静态工厂
    • java.util.stream.IntStream.range()
    • java.nio.file.Files.walk()
  • 自己构建
    • java.util.Spliterator
  • 其他方式
    • Random.ints()
    • BitSet.stream()
    • Pattern.splitAsStream(java.lang.CharSequence)
    • JarFile.stream()

示例

//使用方法        List
list = Arrays.asList("1234","abcd","http","a","Java and Oracle"); Stream
stream = list.stream(); int[] ints = new int[20]; IntStream intStream = Arrays.stream(ints); final Stream
intsStream = Stream.of(ints); Stream
integerStream = Stream.iterate(0, (seed) -> seed+2); integerStream.limit(10).forEach(System.out::println); Stream.generate(() -> Math.random()).limit(10).forEach(System.out::println);

中间操作

1481652-20180912133454767-1515651668.png

/*过滤、切片*/filter从流中排除指定元素limit截断流,限定流中元素个数skip(n)跳过n各元素,超过流元素个数,这返回空流distinct()去除重复元素//链式调用中未执行终止操作时(forEach(...)),不会执行任何操作。//当结果已经满足条件,则不继续执行后方筛选条件,即具备短路特点。/*映射*/map(Function
)将函数应用到每个元素中,并将结果映射为一个新的参数flatmap经函数作为参数应用到每个元素上,返回流连接形成的新流。/*排序*/sorted()sorted((a,b) -> a>b?a:b) /* 想到前段时间阿里的面试题 * 一个巨大的数组统计每个数字的出现次数 */@Testpublic void testMap(){ int a[]=new int[1000]; for(int i=0;i<10000;i++){ a[i]=(int) ( Math.random() *100 ); }//模拟数组 final IntStream stream = Arrays.stream(a); stream.distinct().sorted().forEach((i) ->{ System.out.print("This is "+i+ " count : "); long count = Arrays.stream(a).filter((num) -> num == i).count(); System.out.print(count +"\n"); }); }

终止操作

##查找匹配allMach#是否匹配所有元素anyMatch#至少匹配一个元素noneMatch#是否没有匹配所有元素findFirst#返回匹配的第一个元素findAny#随机返回一个元素count#统计元素个数max#返回最大元素min#返回最小元素##归约reduce(初始值,(下一次执行初始值,流中的元素))Optional
option = employees.stream().map(Employee::getSalary).reduce(Double::sum);#####map-reduce模式######将流中的元素反复匹配执行操作##收集collect#按照一定方式,进行结果收集,即将结果收集起来,可以使用一个工具类Collectorsemployee.stream().map(Employee::getNmae).collect(Collectors.toList());#最终返回值一个List
列表,存储姓名属性Collectors.groupby#分组Collectors.summarizingDoutble#数据处理方式Collectors.joining#字符串

并行流&串行流

Fork/Join框架

将任务分拆成多个小任务,细分到无法再继续分,执行后将所有的结果进行合并得到结果,在并发包的文章里,有写到过,也举了一个计算的例子,这个框架的特点就是,当任务进行拆分后,采用工作窃取模式,可以提高计算时对CPU的利用率。工作窃取模式即当前队列无法获取任务时,将去一个其他拆分队列的任务进行执行。

并行流
List.stream().parallelStream()//执行处理时底层使用Fork/Join框架

接口默认方法与静态方法

原接口中只能有全局静态常量和抽象方法,在java8中可以给接口添加添加默认方法。默认方法冲突时继承大于实现多实现必须重写冲突默认方法。接口可以书写静态方法,使用时,直接使用接口对象调用。

public interface NewInterface{  default String getDefaultMethod(){    return "This is a default Method";  }  public static void getStaticMethod(){    System.out.println("This is a static method from a interface !");  }//NewInterface.getStaticMethod()}

时间API

原时间相关api存在线程安全问题,使用起来较为复杂,java8中添加全新的时间api,多线程可以直接使用,线程安全。

java.time#日期java.time.chrono#特殊时间记录方式java.time.format#日期格式化java.time.temporal#运算推算日期java.time.zone#时区相关设置

操作

//使用时间@Testpublic void testNewDate(){  //LocalDate LocalTime LocalDateTime  LocalDateTime  localDateTime = LocalDateTime.now();  System.out.println(localDateTime);  -----------------------------------  localDateTime = LocalDateTime.of(2018,9,13,23,44);  System.out.println(localDateTime);  -----------------------------------  localDateTime = localDateTime.plusYears(2);  System.out.println(localDateTime);  -----------------------------------  localDateTime = localDateTime.minusYears(2);  System.out.println(localDateTime);}//时间戳@Testpublic void testTimeInstant(){  //Unix 1970.1.1 0.0.0 到现在毫秒 协调世界时  Instant instant = Instant.now();  //设置时间偏移量  instant.atOffset(ZoneOffset.offHours(8));  //获取毫秒  System.out.println(instant.toEpochMilli());  //运算  Instant.ofEpochSecond(60);//1971.1.1 0.1.0  //计算间隔  Duration duration = Duration.between(instant_end , instant_begin);    Period period = Period.between(localDate_end , localDate_begin);  }

其他

注解

java8中可以对方法进行重复注解。

@Repeatable(MoreAnnotations.class)public @interface MoreAnnotation{  String value9() default "注解";}public @interface MoreAnnotations{  MoreAnnotation[] values();}@MoreAnnotation@MoreAnnotation@MoreAnnotationpublic void method(){}

类型注解

private @NonNull Object obj = null//不支持

HashMap

碰撞产生的链表在长度大于8时将会产生红黑树

hashMap内存结构图

ConcurrentHashMap

原16段并发锁改为CAS算法,同时也具备红黑树。

内存模型

1481652-20180912134408169-1963873122.png

转载于:https://www.cnblogs.com/Wu-Zang/p/9631877.html

你可能感兴趣的文章
小div在大div中垂直居中,以及div在页面垂直居中
查看>>
有用的导航栏代码
查看>>
语法错误 : 缺少“;”(在“*”的前面) 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int...
查看>>
2015Web前端攻城之路
查看>>
推荐一个算法网站
查看>>
Python操作MySQL+Redis+MongoDB
查看>>
2017.6.30 Note replace innerHTML split() join()
查看>>
过滤关键词(中间有空格一样过滤)
查看>>
sql 当重复的数据有多条时,保留一条,删除其他重复
查看>>
RFC 4627 JSON
查看>>
Django入门与实践
查看>>
一些面试题(3)
查看>>
算法一枚
查看>>
Spin lock 与mutex 的区别--2011.01.06
查看>>
Java resources
查看>>
python--异常处理
查看>>
MongoDB 之 你得知道MongoDB是个什么鬼 MongoDB - 1
查看>>
数论只会GCD。。。
查看>>
UVA 12506 Shortest Names
查看>>
利用 jQuery 来验证密码两次输入是否相同
查看>>