对java函数、方法、lambda表达式的初步了解

一.java8中的函数与方法
1.流处理
流是一系列数据项,一次只生成一项。程序可以从输 入流中一个一个读取数据项,然后以同样的方式将数据项写入输出流。一个程序的输出流很可能 是另一个程序的输入流。

2.方法引用
File[] hiddenFiles = new File(".").listFiles(File::isHidden);
Java 8的方法引用::语法(即“把这 个方法作为值”)将其传给listFiles方法;

3.Collection主要是为了存储和访问数据,而Stream则主要用 于描述对数据的计算。这里的关键点在于,Stream允许并提倡并行处理一个Stream中的元素。 虽然可能乍看上去有点儿怪,但筛选一个Collection(将上一节的filterApples应用在一个 List上)的最快方法常常是将其转换为Stream,进行并行处理,然后再转换回List
例如:
顺序处理:
List<Apple> heavyApples1 =
inventory. stream().filter((Apple a) -> a.getWeight() > 150)
.collect(toList());
并行处理:List<Apple> heavyApples2 =
inventory. parallelStream().filter((Apple a) -> a.getWeight() > 150) .collect(toList());

二.通过行为参数化传递代码
1.List类型抽象化模版
public interface Predicate<T>{ boolean test(T t);
}
public static <T> List<T> filter(List<T> list, Predicate<T> p){<- 引入类型 参数 T List<T> result = new ArrayList<>(); for(T e: list){
if(p.test(e)){ result.add(e);
}
}
return result;
}
2.用一个 Comparator排序,用Runnable执行一个代码块,以及GUI事件处理。
(1)Comparator排序
// java.util.Comparatorpublic interface Comparator<T> {
public int compare(T o1, T o2);}
因此,你可以随时创建Comparator的实现,用sort方法表现出不同的行为。比如,你可以 使用匿名类,按照重量升序对库存排序:
inventory.sort(new Comparator<Apple>() { public int compare(Apple a1, Apple a2){
return a1.getWeight().compareTo(a2.getWeight()); }
});
如果农民改了主意,你可以随时创建一个Comparator来满足他的新要求,并把它传递给 sort方法。而如何进行排序这一内部细节都被抽象掉了。用Lambda表达式的话,看起来就是 这样:
inventory.sort(
(Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight()));
(2)用Runnable执行一个代码块
// java.lang.Runnable public interface Runnable{
public void run(); }
你可以像下面这样,使用这个接口创建执行不同行为的线程:
Thread t = new Thread(new Runnable() { public void run(){
System.out.println("Hello world"); }
});
用Lambda表达式的话,看起来是这样:
Thread t = new Thread(() -> System.out.println("Hello world"));(3)GUI事件处理
GUI编程的一个典型模式就是执行一个操作来响应特定事件,如鼠标单击或在文字上悬停。
在JavaFX中,你可以使用 EventHandler,把它传给setOnAction来表示对事件的响应:
Button button = new Button("Send");button.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) { label.setText("Sent!!");
} });
这里,setOnAction方法的行为就用EventHandler参数化了。用Lambda表达式的话,看 起来就是这样:
button.setOnAction((ActionEvent event) -> label.setText("Sent!!"));

三.lambda表达式
1.Lambda的基本语法:
(parameters) -> expression
或(请注意语句的花括号)(parameters) -> { statements; }

2.Lambda示例:
使用案例
Lambda案例
对应函数式接口
布尔表达式
(List<String> list) -> list.isEmpty
Predicate<List<String>>
创建对象
()-> new Apple(10)
Supplier<Apple>
消费一个对象
(Apple a)->{System.out.println(a.getWeight());}
Comsumer<Apple>
从一个对象中抽取
(String s)->s.length()
Function<String,Integer>或ToIntFunction<String>
组合两个值
(int a,int b)->a*b
IntBinaryOperator
比较两个对象
(Apple a1,Apple a2)->a1.getWeight().compareTo(a2.getWeight())
Comparator<Apple>或BiFunction<Apple,Apple,Integer>或ToIntBiFunction<Apple,Apple>

@FunctionalInterface定义的一个接口中只能存在一个抽象方法

4.环绕行为模式
(1)行为模式化
你需要一个接收BufferedReader并返回String的Lambda。例 如,下面就是从BufferedReader中打印两行的写法:
String result = processFile((BufferedReader br) -> br.readLine() + br.readLine());

(2)函数式接口传递行为
你需要创建一个能匹配 BufferedReader -> String,还可以抛出IOException异常的接口。让我们把这一接口叫作 BufferedReaderProcessor吧。
@FunctionalInterface public interface BufferedReaderProcessor {
String process(BufferedReader b) throws IOException; }
现在你就可以把这个接口作为新的processFile方法的参数了:
public static String processFile(BufferedReaderProcessor p) throws
IOException {
... }
(3)执行一个行为
你可以在processFile主体内,对得到的BufferedReaderProcessor对象调用process方法执行 处理:
public static String processFile(BufferedReaderProcessor p) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader("data.txt"))) {
return p.process(br);
} 对象
(4)传递Lambda
现在你就可以通过传递不同的Lambda重用processFile方法,并以不同的方式处理文件了。
处理一行:
String oneLine = processFile((BufferedReader br) -> br.readLine());
处理两行:
String twoLines =
processFile((BufferedReader br) -> br.readLine() + br.readLine());

5.java.util.function.Predicate<T>接口定义了一个名叫test的抽象方法,它接受泛型 T对象,并返回一个boolean。
使用Predicate
@FunctionalInterface public interface Predicate<T>{
boolean test(T t); }
public static <T> List<T> filter(List<T> list, Predicate<T> p) { List<T> results = new ArrayList<>(); for(T s: list){
if(p.test(s)){ results.add(s);
} }
return results; }
Predicate<String> nonEmptyStringPredicate = (String s) -> !s.isEmpty(); List<String> nonEmpty = filter(listOfStrings, nonEmptyStringPredicate);

6. Consumer
java.util.function.Consumer<T>定义了一个名叫accept的抽象方法,它接受泛型T 的对象,没有返回(void)。你如果需要访问类型T的对象,并对其执行某些操作,就可以使用 这个接口。
使用Consumer
@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);
}
}
forEach(
Arrays.asList(1,2,3,4,5);
(Integer i) -> System.out.println(i)
);
7.Function
java.util.function.Function<T, R>接口定义了一个叫作apply的方法,它接受一个 泛型T的对象,并返回一个泛型R的对象。
使用Function
@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 s: list){
result.add(f.apply(s)); }
return result; }
// [7, 2, 6] List<Integer> l = map(
Arrays.asList("lambdas","in","action"),
(String s) -> s.length()
);

8.装箱:Java里将原始类型转换为对应的引用类型的机制
拆箱:将引用类型转换为原始类型

9.Lambda表达式引用的局 部变量必须是最终的(final) 或事实上最终的;
闭包:Lambda是对值的封闭,而不是对变量的封闭

10.方法引用
(1)目标引用放在分隔符::前,方法的名称放在后面
Lambda及其等效方法引用的例子
Lambda
等效的方法引用
(Apple a) -> a.getWeight()
Apple : : getWeight
() - > Thread.currentThread().dumpStack()
Thread.currentThread : : dumpStack
(str,i) - > str.substring(i)
String : : substring
(String s) - > System.out.println(s)
System.out : : println
(2)方法引用类型
a.指向静态的方法引用,例如:Integer : : parseInt
b.指向任意类型的实例方法的方法引用,例如:String ::length
c.指向现有对象的实例方法的方法引用(假设你有一个局部变量expensiveTransaction 用于存放Transaction类型的对象,它支持实例方法getValue,那么你就可以写expensive- Transaction::getValue)
(3)构造函数引用
public interface TriFunction<T, U, V, R>{ R apply(T t, U u, V v);
}

11.比较器复合
(1)逆序
inventory.sort(comping(Apple : : getWeight).reversed());//按重量递减排序
(2)比较器链
例如两苹果一样重,按原产国排序
inventory.sort(comparing(Apple : :getWeight)
.reversed()
.thenComparing(Apple : : getCountry));

12.谓词复合
谓词接口包括三个方法:negate、and和or 你可以重用已有的Predicate来创建更复
杂的谓词。
(1)产生现有 Predicate的对象redApple的非
predicate<Apple> notRedApple = redApple.negate();
(2)and方法组合,又红又重的苹果
Predicate<Apple> redAndHeavyApple = redApple.and(a -> a.getWeight() > 150);
(3)or方法组合,150克以上红苹果或绿苹果
Predicate<Apple> redAndHeavyAppleOrGreen = redApple.and(a.getWeight)()>150)
.or(a->"green".equals(a.getColor()));

13.函数复合
(1)andThen方法会返回一个函数,它先对输入应用一个给定函数,再对输出应用另一个函数。
(2)使用compose方法,先把给定的函数用作compose的参数里面给的那个函 数,然后再把函数本身用于结果。
举个例子:
Function<Integer,Integer> h = f.andThen(g);
Function<Integer,Integer> h = f.compose(g);
h = f.andThen(g)是先执行f再执行g,而 h= f.compose(g)是先执行g再执行f
14.积分
(1)integrate,它接受三个参数:一个是f, 还有上下限(这里是H和L)
integrate(f,H,L)
(2)f(x)=x+a
integrate((double x)->x+a,H,L)或integrate((double x)->f(x),H,L)或integrate(C : : f, H, L);

猜你喜欢

转载自blog.csdn.net/lyx_win/article/details/80559191
今日推荐