一、java怎么还在变
1、java在编程语言生态系统中的位置
java虚拟机(JVM)及其字节码可能会变得比java语言本身更重要,而且对于某些应用来说,java可能会被同样运行在JVM上的竞争对手(如Scala或Groovv)取代。
2、流处理
(1)、第一个编程概念就是流处理。介绍一下,流是一系列数据项,一次只生成一项。程序可以从输入流中一个一个读取数据项,然后以同样的方式将数据项写入输入流。一个程序的输出流可能是另一个程序的输入流。
(2)、先把字母转换成小写字母,然后打印出按照字典排序出现在最后的三个单词。其中cat,tr,sort,tail是同时执行的,这样sort就可以在cat或tr完成前先处理头几行。
(3)、在一个更高的抽象层次上写java8程序:思路变成了把这样的流变成那样的流(就像写数据库查询语句时的那种思路),而不是一次只处理一个项目。另一个好处是,java8可以透明地把输入的不想管部分拿到几个cpu内核上去分别执行你的Stream操作流水线——这是几乎免费的并行,用不着费劲搞Thead了。
3、用行为参数把代码传递给方法
java8增强了把方法(你的代码)作为参数传递给另一个方法的能力
4、并行与共享的可变数据
"不能有共享的可变数据"的要求意味着,一个方法可以通过它将参数值转换为结果的方式完全描述的,换句话说,他的行为就像一个数据函数,没有可见的副作用。
二、java中的函数
对象是java中的一等公民,但其他很多java概念(如方法和类等)都是二等公民。
1、方法和lambda作为一等公民
(1)方法引用
File [] hiddenFiles = new File(".").listFiles(File::isHidden); 已经有了函数isHidden,因此只需要用java 8的方法引用::语法(即“把这个方法作为值”)将其传递给listFiles方法。
只要方法中有代码(方法中的可执行部分),那么用方法引用就可以传递代码。
(2)Lambda——匿名函数
除了允许(命名)函数成为一等值外,java8还体现了更广义的将函数作为值的思想,包括Lambda(或匿名函数)。
2、传递代码:一个例子
public static boolean isGreenApple(Apple apple) {
return "green".equals(apple.getColor());
}
public static boolean isHeavyApple(Apple apple) {
return apple.getWeight() > 150;
}
public static List<Apple> filterApples(List<Apple> inventory, Predicate<Apple> p){
List<Apple> result = new ArrayList<>();
for(Apple apple : inventory){
if(p.test(apple)){
result.add(apple);
}
}
return result;
}
List<Apple> inventory = Arrays.asList(new Apple(80,"green"),
new Apple(155, "green"),
new Apple(120, "red"));
List<Apple> greenApples = filterApples(inventory, FilteringApples::isGreenApple);
System.out.println(greenApples);
List<Apple> heavyApples = filterApples(inventory, FilteringApples::isHeavyApple);
System.out.println(heavyApples);
3、从传递方法到Lambda
// [Apple{color='green', weight=80}, Apple{color='green', weight=155}]
List<Apple> greenApples2 = filterApples(inventory, (Apple a) -> "green".equals(a.getColor()));
System.out.println(greenApples2);
// [Apple{color='green', weight=155}]
List<Apple> heavyApples2 = filterApples(inventory, (Apple a) -> a.getWeight() > 150);
System.out.println(heavyApples2);
// []
List<Apple> weirdApples = filterApples(inventory, (Apple a) -> a.getWeight() < 80 ||
"brown".equals(a.getColor()));
System.out.println(weirdApples);
三、流
1、例如:从一个列表中筛选金额较高的交易
(1)传统代码:这种数据迭代的方法称为外部迭代
(2)Steam API:数据处理完全是在库内部进行的,这种思想叫做内部迭代。
2、多线程并非易事
(1)线程可能会同时访问并更新共享变量。因此,如果没有协调好,数据可能会被以外改变,相比一步步执行的顺序模型,这个模型不太好理解。
(2)java8也用Stream API解决了这两个问题:集合处理时的套路和晦涩,以及难以利用多核。
(3)Collection主要是为了存储和访问数据,而Stream则主要用于描述对数据的计算。这里的关键点在于,Stream允许并提倡并行处理一个Stream中的元素。筛选一个Collection的最快方法常常是将其转换为Stream。进行并行处理,然后再转换会List。
顺序处理:
import static java.util.stream.Collectors.toList;
List<Apple> heavyApples = inventory.stream().filter((Apple a) ->a.getWeight()>150).collect(toList());
并行处理:
import static java.util.stream.Collectors.toList;
List<Apple> heavyApples = inventory.parallelStream().filter((Apple a) ->a.getWeight()>150).collect(toList());
四、默认方法
java8接口如今可以包含实现类没有提供实现的方法签名,缺失的方法主体随接口提供了(因此就有了默认实现),而不是有由实现类提供。
五、来自函数式编程的其他好思想
将方法和lambda作为一等值,以及在没有可变共享状态时,函数 或方法可以有效、安全的并行执行。