JAVA8实战第2&3章读书笔记

通过行为参数化来传递代码

#### example:
假如说你要编写一个筛选绿苹果的函数,你可能会这么写:

import java.util.ArrayList;
import java.util.List;

public class test {

  public static List<apple> filter(List<apple> inventory){
    List<apple> result = new ArrayList<apple>();
    for(apple a:inventory){
      if("green".equals(a.getColor())){
        result.add(a);
      }
    }
    return result;
  }
}

如果这个时候需求改为筛选出质量大于150克的苹果呢?加入需求又改为筛选出红色和绿色而且质量大于150克的苹果呢?

可以根据选择标准建模,我们可以实现一个谓词接口,来返回boolean值.

 public interface ApplePredicate{
    boolean test(apple apple);
  }
public static class AppleRedAndHeavyPredicate implements ApplePredicate{
    public boolean test(apple apple){
      return "red".equals(apple.getColor())&&apple.getWeight()>150;
    }
  }

  public static List<apple> filter(List<apple> inventory,ApplePredicate p){
    List<apple> result = new ArrayList<apple>();
    for(apple a:inventory){
      if(p.test(a)){
        result.add(a);
      }
    }
    return result;
  }

那么就可以new 一个谓词对象来做filter方法

List<apple> result = filter(inventory,new AppleRedAndHeavyPredicate());

exam:
编写一个 prettyPrintApple 方法,它接受一个 Apple 的 List ,并可以对它参数化,以
多种方式根据苹果生成一个 String 输出(有点儿像多个可定制的 toString 方法)。例如,你
可 以 告 诉 prettyPrintApple 方 法 , 只 打 印 每 个 苹 果 的 重 量 。 此 外 , 你 可 以 让
prettyPrintApple 方法分别打印每个苹果,然后说明它是重的还是轻的。解决方案和我们
前面讨论的筛选的例子类似。为了帮你上手,我们提供了 prettyPrintApple 方法的一个粗
略的框架

import java.nio.charset.IllegalCharsetNameException;
import java.util.ArrayList;
import java.util.List;

public class printApple {

  public interface Predicate{
    String accept(apple a);
  }

  public static class printFancyApple implements Predicate{
    public String accept(apple a){
      String isHeavy = a.getWeight()>150?"heavy":"light";
      return "A "+isHeavy+" "+a.getColor()+" apple";
    }
  }

  public class printSimpleApple implements Predicate{
    public String accept(apple a){
      return "A "+a.getWeight()+" g "+a.getColor()+" apple";
    }
  }

  public static void printApple(List<apple> Inventory,Predicate p){
    for(apple a: Inventory){
      String output = p.accept(a);
      System.out.println(output);
    }
  }

  public static void main(String [] args)throws Exception{

    apple apple1 = new apple("red",160);

    apple apple2 = new apple("green",80);

    List<apple> inventory = new ArrayList<apple>();

    inventory.add(apple1);
    inventory.add(apple2);

    printApple(inventory,new printFancyApple());

  }
}

使用匿名类

那么你就可以实现随时重写filter方法了

 List<apple> redApples = filter(inventory, new ApplePredicate() {
      @Override
      public boolean test(apple apple) {
        return "red".equals(apple.getColor());
      }
    });

使用匿名函数
List<apple> res = filter(inventory,(apple a) -> "red".equals(a.getColor()));

这样更简洁了.

 public interface Predicate<T>{
    boolean test(T t);
  }

  public static <T> List<T> filter(List<T>list,Predicate<T>p){
    List<T> result = new ArrayList<>();
    for(T t:list){
      if(p.test(t)){
        result.add(t);
      }
    }
    return result;
  }

public static void main(String [] args)throws Exception{

    apple apple1 = new apple("red",160);
    apple apple2 = new apple("green",80);

    List<apple> inventory = new ArrayList<apple>();
    inventory.add(apple1);
    inventory.add(apple2);
    List<Integer> numbers = Arrays.asList(1,2,3,4);
    List<apple> apples = filter(inventory,(apple a) -> "red".equals(a.getColor()));
    List<Integer> evenNums = filter(numbers,(i)-> i%2==0);

  }



    inventory.sort(new Comparator<apple>(){
      @Override
      public int compare(apple apple, apple t1) {
        return apple.getWeight().compareTo(t1.getWeight());
      }
    });
    inventory.sort((apple a1,apple a2) -> a1.getWeight().compareTo(a2.getWeight()));

Lambda表达式

基本语法:

(parameters) -> expression

(parameters) -> {return xxx;}

在哪里以及如何使用Lambda?

在一些函数式接口可以用lambda函数替代.

函数式接口如下:

public interface Comparator<T>{
	int compare(T o1,T o2);
}

public interface Runable{
	void run();
}

public interface Callable <V>{
	V call();
}

在哪里使用Lambda
execute(()->{});
public void execute(Runnable r){
	r.run();
}

Lambda的签名:()->void

这个与runnable中的抽象方法run的签名相匹配

public Callable<String> fetch(){
	return () -> "..";
}

Callable定义了一个签名为()->String的方法
与Lambda方法一致

public interfface Predicate{
	boolean test(apple a);
}
Predicate<apple> p = (apple a) -> a.getWeight();

函数式接口介绍

下面介绍了Predicate,Consumer,map三种函数是接口的定义以及用法

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class test {


  @FunctionalInterface
  public interface Predicate<T>{
    boolean test(T t);
  }

  public static <T> List<T> filter(List<T> list,Predicate<T> p){
    List<T> result = new ArrayList<>();
    for(T t:list){
      if(p.test(t)){
        result.add(t);
      }
    }
    return result;
  }

  @FunctionalInterface
  public interface Consumer<T>{
    void accept(T t);
  }

  public static <T> void forEach(List<T>list,Consumer<T> c){
    for(T i:list){
      c.accept(i);
    }
  }

  @FunctionalInterface
  public interface  Function<T,R>{
    R apply(T t);
  }

  public static<T,R> List<R> map(List<T> list,Function<T,R>f){
    List<R> result = new ArrayList<>();
    for(T t:list){
      result.add(f.apply(t));
    }
    return result;
  }

  public static void main(String [] args)throws Exception {

    //test Predicate
    Predicate<String> nonEmptyPredicate = (String s) -> !s.isEmpty();
    List<String> listsOfString = Arrays.asList("","alex","brecher");
    List<String> result = filter(listsOfString,nonEmptyPredicate);
    Consumer<String> printString = (String s) -> System.out.println(s);
    forEach(result,printString);
    Function<String,Integer> getLen = (String s) -> s.length();
    Function <String,String> flip = (String s) ->{
      try{
          int i = 0;
          int j = s.length()-1;
          StringBuilder strBuilder = new StringBuilder(s);
          while(i<j){
            char temp = s.charAt(i);
            strBuilder.setCharAt(i,s.charAt(j));
            strBuilder.setCharAt(j,temp);
            i++;
            j--;
          }
          return strBuilder.toString();
      }finally {

      }
    };
    List<String> flipList = map(result,flip);
    List<Integer> lenList = map(result,getLen);
    Consumer<Integer> printLen = (Integer i) -> System.out.println(i);
    forEach(lenList,printLen);
    forEach(flipList,printString);
  }

}


result:

alex
brecher
4
7
xela
rehcerb

Java类型分为引用类型和原始类型

前者如(Byte,Integer,Object,List)
后者如(int,double,byte,char)

但是泛型例如Contumer中的T,只能绑定到引用类型.

装箱机制:(boxing)

JAVA中原始类型转换对应的引用类型机制.

拆箱:(unboxing)

JAVA中引用类型转换对应的原始类型机制.

但是自动拆箱和装箱需要更多的内存,性能会受到影响

public interface IntPredicate{
	boolean test(int t);
}

IntPredicate evenNumbers = (int i) -> i % 2 ==0; 无装箱
Predicate oddNumbers = (Integer i) -> i %2 ==1; 有装箱

专门输入参数类型的函数式接口的名称都要加上对应的原始类型前缀,如IntPredicate,DoublePredicate

这也叫特化,

在这里插入图片描述

方法引用

在这里插入图片描述
eg:

  public static void main(String [] args)throws Exception {

    Consumer<String> printString = (String s) -> System.out.println(s);

    List<String> str = Arrays.asList("a","B","A","b");
    str.sort((s1,s2) -> s1.compareToIgnoreCase(s2));
    List<String> str2 = Arrays.asList("a","b","A","B");
    str2.sort(String::compareToIgnoreCase);

    forEach(str,printString);
    forEach(str2,printString);
    
  }

在这里插入图片描述

实战: 用不同的排序策略给一个苹果列表排序

sort函数的签名:

void sort(Comparator<? super E> c)

源码如下:


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.function.Predicate;


public class test {

  public static class AppleComparator implements Comparator<Apple> {

    public int compare(Apple a1,Apple a2){
      return a1.getWeight().compareTo(a2.getWeight());
    }

  }
  public interface Predicate<Apple>{
    boolean test(Apple a);
  }

  public static void main(String [] args){

    //1
    List<Apple>inventory = Arrays.asList(new Apple(30,"green"),new Apple(20,"red"),
            new Apple(25,"yellow"));
    inventory.sort(new AppleComparator());

    System.out.println(inventory);
    inventory.set(1,new Apple(28,"green"));

    //2 自定义函数接口
    inventory.sort(new AppleComparator(){
      @Override
      public int compare(Apple a1,Apple a2){
        return a1.getWeight().compareTo(a2.getWeight());
      }
    });

    System.out.println(inventory);

    //3 Lambda
    inventory.set(1,new Apple(22,"yellow"));
    inventory.sort((Apple a1,Apple a2) -> a1.getWeight().compareTo(a2.getWeight()));
    System.out.println(inventory);
    inventory.set(1,new Apple(32,"red"));

    //4 comparing键值
    inventory.sort(Comparator.comparing((Apple a)->a.getWeight()));
    System.out.println(inventory);

    //5.使用方法引用
    inventory.set(1,new Apple(33,"red"));
    inventory.sort(Comparator.comparing(Apple::getWeight));
    System.out.println(inventory);

    //6.逆序

    inventory.sort(Comparator.comparing(Apple::getWeight).reversed());
    System.out.println(inventory);

    //7.比较器链 如果两个苹果质量一样,那么比较颜色
    inventory.sort(Comparator.comparing(Apple::getWeight)
                  .reversed()
                  .thenComparing(Apple::getColor));
    
  
  }
}

谓词复合

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值