java for底层_Java8相关底层

Java8是往并行方向走的。由面向对象到函数式编程。

在支持函数式编程的同时还可以支持面向对象的开发。

在JDK1.8里面,接口里面可以有实现方法的!默认方法,default。实现这个接口。

接口里面可以有静态方法

注意Lambda表达式的类型势函数。但是在Java中,Lambda表达式是对象!他们必须依赖于一类特别的对象类型-函数式接口

关于Function接口

public classFunctionTest {public static voidmain(String[] args) {

FunctionTest functionTest= newFunctionTest();//传递行为

System.out.println(functionTest.compute(1, value -> {return 10 *value;}));

}public int compute (int a, Functionfunction){//实现,由调用者去实现之

int result =function.apply(a);returnresult;

}

}

解析:

3fcba5e3a08f5e433e2564a35a479f5e.png

单独吧Lambda抽取出来:

public classFunctionTest {public static voidmain(String[] args) {//先把Lambda定义好

Function function = value -> value * 2;

FunctionTest functionTest= newFunctionTest();

System.out.println(functionTest.compute(5, function));

}public int compute(int a, Functionfunction){int result =function.apply(a);returnresult;

}

}

26163a59717fa3103fa91fe6a7ca8dcf.png

多个function之间的串联与先后关系的指定:

public classFunctionTest {public static voidmain(String[] args) {

FunctionTest functionTest= newFunctionTest();

System.out.println(functionTest.compute1(2, value -> value * 3, value -> value *value));

System.out.println(functionTest.compute2(2, value -> value * 3, value -> value *value));

}public int compute1(int a, Function function1, Functionfunction2) {returnfunction1.compose(function2).apply(a);

}public int compute2(int a, Function function1, Functionfunction2) {returnfunction1.andThen(function2).apply(a);

}

}

compose源码:

951ce8a668098e1c372757a23d086daa.png

对比上面的例子,先执行function2 然后将结果赋值给function1去执行

andThen是相反的。

所以,对于 R apply(T t);  要想实现两个输入一个输出,是做不到的。可以通过 BiFunction得到。

public classFunctionTest {public static voidmain(String[] args) {

FunctionTest functionTest= newFunctionTest();

System.out.println(functionTest.compute4(2,3, (value1, value2) -> value1 + value2, value -> value *value));

}public int compute4(int a, int b, BiFunction biFunction, Functionfunction){returnbiFunction.andThen(function).apply(a,b);

}

}

Predicate

e22b25d38a0455b62ac70703fdad96a7.png

filter的参数类型就是Predicate!

函数式编程提供了更高层次的抽象化:

acb032ba4bf2cff4d2a9aedc0dd189f3.png

test() 名字都是抽象的,不具体。比较宏观。

public classFunctionTest {public static voidmain(String[] args) {

List list = Arrays.asList(1,2,3,4,5,6,7);

FunctionTest functionTest= newFunctionTest();

functionTest.conditionFilter(list, item-> item % 2 == 0);

}public void conditionFilter(List list, Predicatepredicate){for(Integer integer : list){if(predicate.test(integer)){

System.out.println(integer);

}

}

}

}

对于Predicate的default函数:

public classFunctionTest {public static voidmain(String[] args) {

List list = Arrays.asList(1,2,3,4,5,6,7);

FunctionTest functionTest= newFunctionTest();

functionTest.conditionFilter(list, item-> item % 2 == 0, item -> item < 6);

}public void conditionFilter(List list, Predicate predicate1, Predicatepredicate2){for(Integer integer : list){//and 返回的是Predicate! 所以继续 .test

if(predicate1.and(predicate2).test(integer)){//if (predicate1.or(predicate2).test(integer)){

if (predicate1.negate().test(integer)){ //取反。满足条件后剩下的//如果两个都满足

System.out.println(integer);

}

}

}

}

静态方法: 返回的也是Predicate

39e1b1ef65ed331b7aff31f91a110a09.png

作用就是判断两个参数是否相等。

public classFunctionTest {public static voidmain(String[] args) {

FunctionTest functionTest= newFunctionTest();//isEqual传进来的是test 然后和参数 “test”比较

System.out.println(functionTest.isEqual(new Date()).test(newDate()));

}public PredicateisEqual(Object object){returnPredicate.isEqual(object);

}

}

Comparator 还是个函数式接口。里面有好几个函数式接口

结合BinaryOperator

Optional  是个容器,可能包含空值,非空值

public classFunctionTest {public static voidmain(String[] args) {//Optional optional = Optional.empty();

Optional optional = Optional.of("valueTest");

optional.ifPresent(item->System.out.println(item));

System.out.println(optional.orElse("world"));

System.out.println(optional.orElseGet( ()-> "hello"));

}

}

public classFunctionTest {public static voidmain(String[] args) {

Employee employee1= newEmployee();

employee1.setName("123");

Employee employee2= newEmployee();

employee2.setName("456");

Company company= newCompany();

company.setName("c1");

List employees =Arrays.asList(employee1, employee2);

company.setEmployees(employees);

List result =company.getEmployees();//if (result != null){//return result;//}else {//return new ArrayList<>();//}//一行代码搞定

Optional optional =Optional.ofNullable(company);

System.out.println(optional.map( item->item.getEmployees()).orElse(Collections.emptyList()));

}

}

注意 Optional类型,不用做参数类型!  因为没有序列化!

作为返回类型,规避null!

方法引用类似于函数指针。‘’

Remember:

function 接收一个 返回一个

Supplier 只返回不接受

总结方法引用分4类:

1. 类名::静态方法名

2. 引用名(对象名)::实例方法名

3.  类名::实例方法名

4. 构造方法引用:: 类名::new

流有个好处,支持并行化,对一个集合进行迭代,流可以并行,多个线程进行处理。对于多核处理性能大大提升。

public classFunctionTest {public static voidmain(String[] args) {

Stream stream = Stream.of("a", "b", "c", "d");

String[] strings= stream.toArray(length -> newString[length]);

Arrays.asList(strings).forEach(System.out::println);

}

}

改造成Lambda表达式构造函数引用:  通过构造函数引用的方式将数组传递进去

public classFunctionTest {public static voidmain(String[] args) {

Stream stream = Stream.of("a", "b", "c", "d");

String[] strings= stream.toArray(String[]::new);

Arrays.asList(strings).forEach(System.out::println);

}

}

public classFunctionTest {public static voidmain(String[] args) {

Stream stream = Stream.of("a", "b", "c", "d");

List list1 = stream.collect(() -> newArrayList(),

(theList, item)->theList.add(item),

(theList1, theList2)->theList1.addAll(theList2));//方法二

List list2 = stream.collect(LinkedList::new, LinkedList::add, LinkedList::addAll);

list.stream().forEach(System.out::println);

}

}

public classFunctionTest {public static voidmain(String[] args) {

Stream stream = Stream.of("a", "b", "c", "d");

String str=stream.collect(Collectors.joining()).toString();

System.out.println(str);

}

}

flatMap去操作:

public classFunctionTest {public static voidmain(String[] args) {

Stream> listStream = Stream.of(Arrays.asList(1), Arrays.asList(2, 3), Arrays.asList(4, 5, 6));//每个List转成Stream

listStream.flatMap( theList ->theList.stream())

.map( item-> item *item).forEach(System.out::println);

}

}

正确使用Optional:

public classFunctionTest {public static voidmain(String[] args) {

Stream stream =Stream.generate(UUID.randomUUID()::toString);//返回的是个Optional可以调用get方法。 流里面的第一个元素为啥返回Optional。避免异常。如果流里面没有元素呢?规避之

System.out.println(stream.findFirst().get());//如果存在元素的话...

stream.findFirst().ifPresent(System.out::println);//可以创建空的流

Stream stream1 =Stream.empty();

stream1.findFirst().ifPresent(System.out::println);

}

}

public classFunctionTest {public static voidmain(String[] args) {

Stream stream = Stream.iterate(1, item -> item + 2).limit(6);

IntSummaryStatistics summaryStatistics= stream.filter(item -> item > 2)

.mapToInt(item-> item * 2).skip(2).limit(2).summaryStatistics();

System.out.println( summaryStatistics.getMax());

System.out.println( summaryStatistics.getMin());

}

}

例子:Map: 中间操作,延迟操作。遇到终止操作时候才会执行之

public classFunctionTest {public static voidmain(String[] args) {

List list = Arrays.asList("hello", "world", "how are you");

list.stream().map(

item->{

String result= item.substring(0, 1).toUpperCase() + item.substring(1);

System.out.println("----->");returnresult;

}

).forEach( System.out::println);

}

}

Map和flatMap

public static voidmain(String[] args) {

List list = Arrays.asList("hello welcome", "world hello");

//返回的List string类型的数组 四个数组对象不是不同的!

List result = list.stream()

// Stream map(Function super T, ? extends R> mapper);

.map(item -> item.split(" ")).distinct().collect(Collectors.toList());

result.forEach(

item -> Arrays.asList(item).forEach(System.out::println)

);

//flatMap System.out.println("----->flatMap"); List resultFlatMap = list.stream().map(item -> item.split(" "))// Stream flatMap(Function super T, ? extends Stream extends R>> mapper);

//将数组类型 转成 String类型

.flatMap(Arrays::stream) // 接收的是一个数组类型。返回Stream类型。这样返回四个Stream。 调用FlatMap把四个Stream合并成一个!

.distinct().collect(Collectors.toList());

resultFlatMap.forEach(System.out::println);

}

c4550cb5444cfdf9e9a3f857de4e5a3a.png

199990263a3261de975fda6a876b7fd2.png

分析 FlatMap将结果打平了,结果放在一个流里面。

上述对于 FlatMap的使用, 首先map映射成字符串数组类型的内容, 然后将字符串数组打平。打平成一个Stream。即: 将 Stream  ------> Stream

public classFunctionTest {public static voidmain(String[] args) {

List list1 = Arrays.asList("你好", "哈哈");

List list2 = Arrays.asList("zhangsan", "lisi", "wangwu");

List result = list1.stream().flatMap(item -> list2.stream().map(item2 -> item + " " +item2)).collect(Collectors.toList());

result.forEach(System.out::println);

}

}

afbb43d0f1b1a1f5712998822fa7da45.png

Stream:

和迭代器不同的是,Stream可以并行化操作,迭代器只能命令式、串行化操作

当使用串行方式遍历时,每特item读完后再读下一个

使用并行去遍历时,数据会被分成多段,其中每一个都在不同的线程中处理,然后将结果一起输出。

Stream的并行操作依赖于Java7中引入的Fork/Join框架。任务分解成小任务。

集合关注的是数据与数据存储

流关注的是数计算,流与迭代器类似的一点是: 流复发重复使用或者消费的。

中间操作都会返回一个Stream对象,比如 Stream Stream  比如 mapToInt返回 Stream

public class FunctionTest {

public static void main(String[] args) {

Employee employee1 = new Employee("a");

Employee employee2 = new Employee("a");

Employee employee3 = new Employee("b");

Employee employee4 = new Employee("c");

List list = Arrays.asList(employee1, employee2, employee3, employee4);

Map nameCountMap = list.stream().collect(Collectors.groupingBy(Employee::getName, Collectors.counting()));

System.out.println(nameCountMap);

}

}

4a782bc00f0f6d964d88cf1d9aa7ea9c.png

list.stream().collect(Collectors.groupingBy(Employee::getName, Collectors.averagingDouble(Employee::getScore));

分组:group by

分区: partition by 区别group by 只能分两组 ,比如 true false。 90以上及格,以下不及格

collect是Stream提供的一个方法。Collector作为Collect方法的参数。Collector接口非常重要,分析之:

Collector是一个接口,文档解释“它是一个可变的汇聚操作,将输入元素累积到一个可变的结果容器中;它会在所有元素处理完毕之后,将累积结果转换为一个最终的表示(这是一个可选操作。支持串行并行两种方式执行。

注意: 并行不一定比串行块,因为并行涉及到线程切换。比如cpu 2核的,生成四个线程。势必四个线程去增强这两个核心,会存在上下文切换。

Collectors本身提供了关于Collectors的常见汇聚实现,Collectors本身是一个工厂。

Collector是由四个元素组成的

combiner函数,有四个线程同时去执行,那么就会生成四个部分结果。然后合并成一个。用在并行流的场景。

为了确保串行与并行操作的结果等价性,Collector函数需要满足两个条件,identity(同一性)与associativity(结合性)。

public interface Collector T:集合或者流中的每个元素类型, A可变容器类型, R:结果类型

·

public classFunctionTest {public static voidmain(String[] args) {

Employee employee1= new Employee("a", 12);

Employee employee2= new Employee("a", 23);

Employee employee3= new Employee("b", 43);

Employee employee4= new Employee("c", 34);

List employees =Arrays.asList(employee1, employee2, employee3, employee4);

String collect1= employees.stream().map(Employee::getName).collect(Collectors.joining(","));//连续分组

Map>> collect =employees.stream()

.collect(Collectors.groupingBy(Employee::getScore, Collectors.groupingBy(Employee::getName)));//分区

Map> collect2 = employees.stream().collect(Collectors.partitioningBy(e -> e.getScore() > 3));//连续分区

Map>> collect3 = employees.stream().collect(Collectors.partitioningBy(e -> e.getScore() > 80, Collectors.partitioningBy(e -> e.getScore() > 5)));//综合实战

Map collect4 = employees.stream().collect(Collectors.partitioningBy(employee -> employee.getScore() > 90, Collectors.counting()));

Map collect5 =employees.stream().collect(Collectors.groupingBy(Employee::getName,//收集然后XXX

Collectors.collectingAndThen(Collectors.minBy(Comparator.comparingInt(Employee::getScore)),

Optional::get)));

}

}

排序:

Collector.sort() 本质上是调用 list.sort()

public classFunctionTest {public static voidmain(String[] args) {

List list = Arrays.asList("helloWorld", "nihao", "java");

Collections.sort(list, (item1, item2)-> {return (item1.length() -item2.length());});

System.out.println(list);//当lambda没法推断类型时候,指定下

Collections.sort(list, Comparator.comparingInt((String item) ->item.length()).reversed());

list.sort(Comparator.comparingInt(String::length).reversed());

list.sort(Comparator.comparingInt((String item)->item.length()).reversed());//不区分大小写的排序,两个排序规则. 先升序,然后XXX.两个比较规则,第一个相同就调用第二个方法。

Collections.sort(list, Comparator.comparingInt(String::length).thenComparing(String.CASE_INSENSITIVE_ORDER));

Collections.sort(list, Comparator.comparingInt(String::length).thenComparing( (item1, item2)->item1.toLowerCase().compareTo(item2.toLowerCase())));

Collections.sort(list, Comparator.comparingInt(String::length).thenComparing(Comparator.comparing(String::toLowerCase)));//长度希望等的,才需要进行第二次比较。小写进行比较,小写逆序。

Collections.sort(list, Comparator.comparingInt(String::length).thenComparing(Comparator.comparing(String::toLowerCase, Comparator.reverseOrder())));

Collections.sort(list, Comparator.comparingInt(String::length).reversed().thenComparing(Comparator.comparing(String::toLowerCase, Comparator.reverseOrder())));//多级排序

Collections.sort(list, Comparator.comparingInt(String::length).reversed()//相同的(比较结果为0的,继续使用下面的方法)

.thenComparing(Comparator.comparing(String::toLowerCase, Comparator.reverseOrder()))//是否起作用,取决于前面的比较情况结果

.thenComparing(Comparator.reverseOrder()));

}

}

定义实现自己的收集器:

/**

* 1.实现接口时候,要定义好泛型

* 2.

*/

public class MySetCollector implements Collector, Set> {

/**

* 提供一个空的容器,供accumulator 后续方法调用

* @return

*/

@Override

public Supplier> supplier() {

System.out.println("-----> supplier");

return HashSet::new;

}

/**

* 累加器类型的,接收两个参数不返回值

* @return

*/

@Override

public BiConsumer, T> accumulator() {

System.out.println("-----> accumulator");

//通过方法引用的方式返回了一个 BiConsumer 对象

// return Set::add;

return (set, item) -> set.add(item);

}

/**

* 将并行流,多个线程所执行的结果合并起来

* @return

*/

@Override

public BinaryOperator> combiner() {

// 把一个部分结果,添加到另外一个部分结果中

System.out.println("------> combiner");

return (set1, set2) -> {

set1.addAll(set2);

return set1;

};

}

/**

* 多线程情况下,最后一步要执行的。返回最终的结果类型。返回结果容器给用户。

* @return

*/

@Override

public Function, Set> finisher() {

// return t -> t;

return Function.identity();

}

/**

* 返回一个set集合,表示当前的收集器诸多独特性。

* @return

*/

@Override

public Set characteristics() {

System.out.println("----->characteristics");

// 直接返回一个不可变的集合,参数为指定的特性

return Collections.unmodifiableSet(EnumSet.of(IDENTITY_FINISH, UNORDERED));

}

public static void main(String[] args) {

List list = Arrays.asList("hello", "world", "welcome", "hello");

Set collect = list.stream().collect(new MySetCollector<>());

System.out.println(collect);

}

}

d86ae3e59bb4182c3c75d347d9871e8c.png

看下面例子:

public class MySetCollector2 implements Collector, Map>{

@Overridepublic Supplier>supplier() {

System.out.println("supplier invoked");return HashSet::new;

}

@Overridepublic BiConsumer, T>accumulator() {

System.out.println("accumulator invoked");return (set, item) ->{

set.add(item);

};

}

@Overridepublic BinaryOperator>combiner() {

System.out.println("combiner invoked");return (set1, set2) ->{

set1.addAll(set2);returnset1;

};

}

@Overridepublic Function, Map>finisher() {

System.out.println("finisher invoked");return set ->{

Map map = new HashMap<>();

set.stream().forEach(

item->map.put(item, item)

);returnmap;

};

}

@Overridepublic Setcharacteristics() {

System.out.println("characteristics invoked!");returnCollections.unmodifiableSet(EnumSet.of(Characteristics.UNORDERED));

}public static voidmain(String[] args) {

List list = Arrays.asList("hello", "world", "welcome", "a", "b", "c");

Set set = new HashSet<>();

set.addAll(list);

System.out.println("set"+set);

Map collect = set.stream().collect(new MySetCollector2<>());

System.out.println(collect);

}

}

520e1fe601a3c5b9f0607e59112d69c7.png

收集器:

对于Collectors惊天工厂类来说,其实现一共分为两种情况:

通过ColletcorImpl来实现

通过reduceing方法来实现(reducing方法本身又是通过CollectorImpl来实现)

关于toList()

public static Collector>toList() {return new CollectorImpl<>((Supplier>) ArrayList::new, List::add,

(left, right)-> { left.addAll(right); returnleft; },

CH_ID);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值