Java 8 Lamda

Java 8 Lamda

we all know Lambda project is a big enhancement to the java programming language. so let’s start to learn the grammer.

Background

java is, an object-oriented programming language. but the language tend to be relatively heavyweight.
the user to provide an instance of the interface when invoking the API.for example:

public interface ActionListener{
void actionPerformed(ActionEven e);
}

you can easily to find the above interface in swing. this is also the reason why i quit the calix company. cry!!!


button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
ui.dazzle(e.getModifiers())
}
})

In this respect, anonymous inner classes are imperfect for a number of reasons.
1. Bulk syntax
2. Confusion surrounding the meaning of names and this
3. Inflexibel class-loading and instance-creation semantics
4. Inability to capture non-final local variables
5. Inability to abstract over control flow

Function interfaces

The anonymous inner class approach also has the nice property of fitting very cleanly into java’s type system.
the reasons:
1. interfaces are already an intrinsic part of the type system.
2. they natrually have a runtime representation
3. they carry with them informal contracts expressed by javadoc comments,such as an assertion that an operation is commutative.

the interface ActionListener,used above.has just one method. we’ll give all interfaces that have just one method a name:functional interfaces.(These were previously called SAM Types,which stood for “Single Abstract Method”)

However,API authors may additional capture the design intent that an interface be functional with the @FunctionalInterface annotation.

A type like “function from a String and an Object to an init“ might be expressed as (String,Object)->int.This idea was considered and rejected, at least for now.

In addition,Java SE 8 adds a new package,java.util.function,which contains functional interfaces that are expected to be commonly use,such as :

Predicate<T> -- a boolean-valued property of an object
Consumer<T> -- an action to be performed on an object
Function<T,R> -- a function transforming a T to a R
Supplier<T> -- provide an instance of a T(such as a factory)
UnaryOperator<T> -- a function from T to T
BinaryOperator<T> -- a function from (T,T) to T

//Todo i dont the how to use them

Lambda expressions


(int x,int y)->x+y
()->42
(String s)->{System.out.println(s);}

1. The frist expression takes two integer arguments, named x and y, and returns their sum.
2. the second taks no arguments and returns the integre 42.
3. the third takes a string and prints it to the console,returning nothing.

Here are some examples of lambda expressions appearing in statements:
`
FileFilter java=(File f)->f.getName().endsWith(“.java”);
String user=doPrivileged(()-> System.getProperty(“user.name”));
new Thread(()->{
connectToService();
sendNotification();
}).start();

`

Target typing


ActionListener 1=(ActionEvent e)->ui.dazzle(e.getModifiers());


Comparator<String> c =(s1,s2)->s1.compareToIgnoreCase(s2);

Contexts for target typing

In the first three cases,the target type is simply the type being assigned to or returned.


Comparator<String> c;
c=(String s1,String s2)->s1.compareToIgnoreCase(s2);
public Runnable toDoLater(){
return ()->{
System.out.println(“later”);
};
}


List<Person> ps=..
String <String> names=ps.stream().map(p->p.getName());

The map() method is generic in R,where the parameter of map() is a Function

lexical scoping

Lambda expressions are much simpler:they do not inherit any names from a supertype,nor do they introduce a new level of scoping.Instead, they are lexcially scoped,meaning names in the body are interpreted just as they are in the enclosing environment(with the addition of new names for the lambda expression’s formal parameters). As a natural extension, the this keyword and references to its members have the same meaning as they woild immediately outside the lambda expression.


public class Hello{
Runnable r1=()->{System.out.println(this)}
Runnable r2=()->{System.out.println(toString());}
}
public String toString(){ return “hello,world!”;}
public static void main(String... args){
new Hello().r1.run();
new Hello().r2.run();
}

Variable capture

Method references

Lambda expressions allow us to define an anonymous method and treadt it as an instance of a functional interface. It is often desirable to do the same with an existing method.


Person[] people=...
Comparator<Person> byName=Comparator.comparing(p->p.getName());
Arrays.sort(people,byName);

we can rewirte this to use a method reference to Persion.getName() instead:


Comparator<Person> byName=Comparator.comparing(Person::getName);

Here, the expression Person:getName can be considered shorthand for a lambda expression which simply invokes the named method with its arguments,and returns the result.While the method reference may not (in this case)be any more syntactcally compact,it is clearer – the method that we want to call has a name, and so we can refer to it directly by name.

Because the functional interface method’s parameter types act as arguments in an implicit method invocation, the referenced method signature is allowed to manipulate the parameters – via widening, boxing,grouping as a variable- arity array,etc– just like a methond invocation.


Consumer<Integer> b1=System::exit;
Consumer<String[]> b2=Arrays::sort;
Consumer<String> b3=MyProgram::main;
Runnable r=MyProgram::main;

Kinds of method references

There ara several differenct kinds of method reference,each with slightly different syntax:

  1. A static method (ClassName:methName)
  2. An instance method of a particular object(instanceRef::methName)
  3. A super method of a particular object(super::methName)
  4. An instance method of an arbitrary object of a particular type(ClassName:methName)
  5. A class constructor reference(ClassName::new)
  6. An array constructor reference(TypName[]:new)

For a static method reference,the class to which the method belongs preceds the :: delimiter,such as in Integer::sum.

For a reference to an instance method of a particular object, an expression evaluating to delimiter:

Set<String> knownName=...
Predicate<String> isKnown=knowNames::contains;

Here, the implicit lambda expression would capture the String object referred to by knownNames,and the body would invoke Set.contains using that object as the receiver.


Function<String,String> upperfier=String::toUpperCase;

Note that the syntax for a static method reference might also be interpreted as a reference to an instance method of a class.
Constructors can be referenced in much the same was as static methods by using the name new:

SocketImplFactory factory=MySocketImpl::new;

If a class has multiple constructors,the target type’s method signature is used to select the best match in the same way that a constructor invocation is resolved.

There is a special syntactic form of constructor references for arrays,which treats arrays if they had a constructor that accepts an int parameter.For example:


IntFunction<int[]> arrayMaker=int[]:new;
int[] array=arrayMaker.apply(10);

Default and static interface methods

In addition to allowing code in interfaces in the form of default methods, Java SE 8 also introduces the ability to place static methods in interfaces as well. This allows helper methods that are specific to an interface to live with the interface,rather than in a side class (which is often named for the plural of the interface).For example,comparator acquired static helper methods for making comparators,which takes a function that extracts a Comparabel Sork key and produces a Comparator:

public static<T,U extends Comparable<?super U>>
Comparator<T> comparing(Function<T,U> keyExtractor){
return (c1,c2)-> keyExtractor,apply(c1).compareTO(keyExtractor,apply(c2));
}

Inheritance of default methods

Puting it together


List<Perion> people=...
Collections.sort(people.new Comparator<Persion>(){
public int compare(Person x,Person y){
return x.getLastName().compareTo(y.getLastName());
}
})

This is a very verbose way to write “sort people by last name”!

With lambda expressions,we can make this expression more concise:

Collections.sort(people,(Person x,Person y)->x.getLastName(),compareTo(y.getLastName()));

However,while more concise,it is not any more abstract;it still burdens the programmer with the need to do the actual comparison .small changes to the libraries can help here, such the static comparing method added to Comparator:


Collections.sort(people,Comparator.comparing((Person p)->p.getLastName()));

This can be shortened by allowing th compiler to infer the type of the lambda parameter, and importing the comparing method via a static import:


Collections.sort(people,comparing(p->p.getLastName));

The lambda in the above expression is simply a forwarder for the existing method getLastName, we can use method references to reuse the existing method in place of the lambda expression.


Collection.sort(people,comparing(Person::getLastName));

Finally,the use of an ancillary method like Collection.sort is undesirable for many reasons: it is moreve verbose;it can’t be specialized for each data structure that implements List; and it undermines the value of the List interface since users can’t easily discover the static sort method when inspecting the documentation for List.

Default methods provide a more object-oriented solution for this problem, where we’ve added a sort() method to List:

people.sort(comparing(Person::getLastName));

If we add a default method reversed() to Comparator,which produces a Comparator that uses the same sort key but in reverse order,we can just as easily express a descending sort:


people.sort(comparing(Person:getLastName).reversed());

That’s all.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值