Tuesday, March 1, 2016

JDK 8 Lambda



https://zhuanlan.zhihu.com/p/35843517
lambda表达式最终会返回一个实现了指定接口的实例,看上去和内部匿名类很像,但有一个最大的区别就是代码里面的this,内部匿名类this指向的就是匿名类,而lambda表达式里面的this指向的当前类。
lambda表达式里面,会把lambda表达式在本类中生成一个以lambda$+数字的方法。关键点:该方法不一定是static的方法,是static还是非static,取决于lambda表达式里面是否引用了this。这就是为什么lambda表达式里面的this指向的是本地,因为他在本类里面创建了一个方法,然后把lambda表达式里面的代码放进去。

   // lambda实现
    // 下面会自动生成lambda$0方法,由于使用了this,所以是非static方法
    new Thread(() -> {
      System.out.println("这里的this指向当前的ThisDemo类:" + this.name);
    }).start();

    // lambda实现
    // 下面会自动生成lambda$1方法,由于使用了this,所以是static方法
    new Thread(() -> {
      System.out.println("这里没有引用this,生成的lambda1方法是static的");
    }).start();
https://zhuanlan.zhihu.com/p/43719291
public class Lazy<T> {
private transient Supplier<T> supplier;
private volatile T value;
public Lazy(Supplier<T> supplier) {
this.supplier = Objects.requireNonNull(supplier);
}
public T get() {
if (value == null) {
synchronized (this) {
if (value == null) {
value = Objects.requireNonNull(supplier.get());
supplier = null;
}
}
}
return value;
}
public <R> Lazy<R> map(Function<T, R> mapper) {
return new Lazy<>(() -> mapper.apply(this.get()));
}
public <R> Lazy<R> flatMap(Function<T, Lazy<R>> mapper) {
return new Lazy<>(() -> mapper.apply(this.get()).get());
}
public Lazy<Optional<T>> filter(Predicate<T> predicate) {
return new Lazy<>(() -> Optional.of(get()).filter(predicate));
}
public static <T> Lazy<T> of(Supplier<T> supplier) {
return new Lazy<>(supplier);
}
}


https://blog.jooq.org/2017/03/17/a-nice-api-design-gem-strategy-pattern-with-lambdas/
jOOQ knows a simple type called Converter. It’s a simple SPI, which allows users to implement custom data types and inject data type conversion into jOOQ’s type system. 
public interface Converter<T, U> {
    U from(T databaseObject);
    T to(U userObject);
    Class<T> fromType();
    Class<U> toType();
}
  • Why do we need to give this class a name?
  • Why do we need to override methods?
  • Why do we need to handle nulls ourselves?
Now, we could write some object oriented libraries, e.g. abstract base classes that take care at least of the fromType() and toType() methods, but much better: The API designer can provide a “constructor API”, which allows users to provide “strategies”, which is just a fancy name for “function”. One function (i.e. lambda) for each of the four methods. For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public interface Converter<T, U> {
    ...
    static <T, U> Converter<T, U> of(
        Class<T> fromType,
        Class<U> toType,
        Function<? super T, ? extends U> from,
        Function<? super U, ? extends T> to
    ) {
        return new Converter<T, U>() { ... boring code here ... }
    }
    static <T, U> Converter<T, U> ofNullable(
        Class<T> fromType,
        Class<U> toType,
        Function<? super T, ? extends U> from,
        Function<? super U, ? extends T> to
    ) {
        return of(
            fromType,
            toType,
            // Boring null handling code here
            t -> t == null ? null : from.apply(t),
            u -> u == null ? null : to.apply(u)
        );
    }
}
From now on, we can easily write converters in a functional way. For example, our HexConverter would become:
1
2
3
4
5
6
7
Converter<String, Integer> converter =
Converter.ofNullable(
    String.class,
    Integer.class,
    s -> Integer.parseInt(s, 16),
    Integer::toHexString
);
If you have an interface of the form:
1
2
3
4
5
6
interface MyInterface {
    void myMethod1();
    String myMethod2();
    void myMethod3(String value);
    String myMethod4(String value);
}
Then, just add a convenience constructor to the interface, accepting Java 8 functional interfaces like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// You write this boring stuff
interface MyInterface {
    static MyInterface of(
        Runnable function1,
        Supplier<String> function2,
        Consumer<String> function3,
        Function<String, String> function4
    ) {
        return new MyInterface() {
            @Override
            public void myMethod1() {
                function1.run();
            }
            @Override
            public String myMethod2() {
                return function2.get();
            }
            @Override
            public void myMethod3(String value) {
                function3.accept(value);
            }
            @Override
            public String myMethod4(String value) {
                return function4.apply(value);
            }
        }
    }
}
As an API designer, you write this boilerplate only once. And your users can then easily write things like these:
1
2
3
4
5
6
7
// Your users write this awesome stuff
MyInterface.of(
    () -> { ... },
    () -> "hello",
    v -> { ... },
    v -> "world"
);

http://javaonfly.blogspot.com/2017/11/java8effective-use-of-consumer.html
Consumer<String> consumer = manager::createAndDisplayEmail;
consumer.accept("This is a mail from Javaonfly");


prior to Java8, we don’t have privilege to treat method as variable so we can’t pass a method into another method as an argument like we usually do in case of variable, to achieve the same we have to pass an Object which holds that method, so to reuse the method either we have to make it static or has to pass the Object . Which is OK but it has a problem unnecessary we have to carry the context(i.e Object) while we need only the method definition. In Java 8 now we can easily hold the method reference using appropriate interface without context, and reuse the method later.

Consumer as a Strategy Pattern:

Consumer as a Filter Chain Pattern :
As Consumer takes one input and produce nothing, so it behaves like a terminal operation, but sometimes we need to apply series of actions on the input.  Generally in OO design we do it through FilterChain where we will create an interface with a method doFilter() then implements multiple classes based on the action which we apply on the input, also create a FilteManger class which iterate over the filters and apply the filter on input, or a filter apply itself then delegate the call to next filter. The Same concept can be achieved through Consumer interface where each filter implementation represents a method and a Higher-order function treat as Filter manager which will iterate over methods and apply it to the input.

   public void applyFilter(List<Consumer<String>> filterList,String emailBody){
      filterList.forEach(filter->filter.accept(emailBody));
   }
   
   public static void main(String[] args) {
      EmailManager manager = new EmailManager();
      String body ="This is a mail from Javaonfly";
      List<Consumer<String>> filterList=new ArrayList<Consumer<String>>();
      filterList.add(manager::spellChecker);
      filterList.add(manager::grammarChecker);
      filterList.add(manager::formatChecker);
      manager.applyFilter(filterList, body);
     
   }
http://www.mkyong.com/java8/java-8-convert-list-to-map/
        Map<Integer, String> result1 = list.stream().collect(
                Collectors.toMap(Hosting::getId, Hosting::getName));

Map<String, Choice> result =
    choices.stream().collect(Collectors.toMap(Choice::getName,
                                              Function.identity()));

Java 8 Lambdas
Macro macro = new Macro();
macro.record(editor::open);
macro.run();

Compressor gzipCompressor = new Compressor(GZIPOutputStream::new);
moon.startSpying(name -> {
    if (name.contains("Apollo"))
        System.out.println("We made it!");
});

Growing Object-Oriented Software, Guided by Tests


logger.debug(() -> "Look at this: " + expensiveOperation());

ThreadLocal allows us to create a factory that generates at most one value per thread. This is an easy way of ensuring that a thread-unsafe class can be safely used in a concurrent environment.
THE LONELY OVERRIDE
ThreadLocal<Album> thisAlbum = ThreadLocal.withInitial(() -> database.lookupCurrentAlbum());

public long countFeature(ToLongFunction<Album> function) {
    return albums.stream()
            .mapToLong(function)
            .sum();
}
public long countTracks() {return countFeature(album -> album.getTracks().count());}

Don’t use a lambda expression. - Do use method references.

passing code as data
List<String> list = mock(List.class);
when(list.size()).thenAnswer(inv -> otherList.size());
assertEquals(3, list.size());

the streams library contains a method that lets you look at each value in turn and also lets you continue to operate on the same underlying stream
.peek(nation -> System.out.println("Found nationality: " + nation))
.collect(Collectors.<String>toSet());

a breakpoint can be set on the body of the peek method.
If you want to unit test a lambda expression of any complexity, extract it to a regular method.


https://www.javacodegeeks.com/2014/04/playing-with-java-8-lambdas-and-concurrency.html
Mutable variable capture in anonymous Java classes
http://eclipsesource.com/blogs/2013/08/19/mutable-variable-capture-in-anonymous-java-classes/

http://blog.takipi.com/the-dark-side-of-lambda-expressions-in-java-8/
The Java platform is built out of two main components. The JRE, which JIT compiles and executes bytecode, and the JDK which contains dev tools and the javac source compiler. 

But the farther away you get from Java – the more that distance grows. When you look at Scala which is a functional language, the distance between the source code and the executed bytecode is pretty big. Large amounts of synthetic classes, methods and variables are added by the compiler to get the JVM to execute the semantics and flow controls required by the language.
With the push to add new elements into Java, the distance between your code and the runtime grows, which means that what you’re writing and what you’re debugging will be two different things.

http://stackoverflow.com/questions/20938095/difference-between-final-and-effectively-final
I'm playing with lambdas in Java 8 and I came across warning local variables referenced from a lambda expression must be final or effectively final. I know that when I use variables inside anonymous class they must be final in outer class, but still - what is the difference between finaland effectively final?
A variable or parameter whose value is never changed after it is initialized is effectively final.
Basically, if the compiler finds a variable does not appear in assignments outside of its initialization, then the variable is considered effectively final.

Simplifying ReadWriteLock with Java 8 and lambdas
http://www.nurkiewicz.com/2014/03/simplifying-readwritelock-with-java-8.html
public class Buffer {
    private final int capacity;
    private final Deque<String> recent;
    private int discarded;
    private final Lock readLock;
    private final Lock writeLock;
    public Buffer(int capacity) {
        this.capacity = capacity;
        recent = new ArrayDeque<>(capacity);
        final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
        readLock = rwLock.readLock();
        writeLock = rwLock.writeLock();
    }
    public void putItem(String item) {
        writeLock.lock();
        try {
            while (recent.size() >= capacity) {
                recent.removeFirst();
                ++discarded;
            }
            recent.addLast(item);
        } finally {
            writeLock.unlock();
        }
    }
    public List<String> getRecent() {
        readLock.lock();
        try {
            final ArrayList<String> result = new ArrayList<>();
            result.addAll(recent);
            return result;
        } finally {
            readLock.unlock();
}
    public int getDiscardedCount() {
        readLock.lock();
        try {
            return discarded;
        } finally {
            readLock.unlock();
        }
    }
    public int getTotal() {
        readLock.lock();
        try {
            return discarded + recent.size();
        } finally {
            readLock.unlock();
        }
    }
    public void flush() {
        writeLock.lock();
        try {
            discarded += recent.size();
            recent.clear();
        } finally {
            writeLock.unlock();
        }
    }

However with lambda expressions we can wrap cross-cutting concerns in a utility class like this:
public class FunctionalReadWriteLock {
    private final Lock readLock;
    private final Lock writeLock;
    public FunctionalReadWriteLock() {
        this(new ReentrantReadWriteLock());
    }
    public FunctionalReadWriteLock(ReadWriteLock lock) {
        readLock = lock.readLock();
        writeLock = lock.writeLock();
    }
    public <T> T read(Supplier<T> block) {
        readLock.lock();
        try {
            return block.get();
        } finally {
            readLock.unlock();
        }
    }
    public void read(Runnable block) {
        readLock.lock();
        try {
            block.run();
        } finally {
            readLock.unlock();
        }
    }
    public <T> T write(Supplier<T> block) {
        writeLock.lock();
        try {
            return block.get();
        } finally {
            writeLock.unlock();
        }
1
2
3
4
5
6
7
8
9
10
11
public void write(Runnable block) {
        writeLock.lock();
        try {
            block.run();
        } finally {
            writeLock.unlock();
        }
    }
}
As you can see we wrap ReadWriteLock and provide a set of utility methods to work with. In principle we would like to pass a Runnable or Supplier<T> (interface having single T get() method) and make sure calling it is surrounded with proper lock. We could write the exact same wrapper class without lambdas, but having them greatly simplifies client code:

public class Buffer {
    private final int capacity;
    private final Deque<String> recent;
    private int discarded;
    private final FunctionalReadWriteLock guard;
    public Buffer(int capacity) {
        this.capacity = capacity;
        recent = new ArrayDeque<>(capacity);
        guard = new FunctionalReadWriteLock();
    }
    public void putItem(String item) {
        guard.write(() -> {
            while (recent.size() >= capacity) {
                recent.removeFirst();
                ++discarded;
            }
            recent.addLast(item);
        });
    }
    public List<String> getRecent() {
        return guard.read(() -> {
            return recent.stream().collect(toList());
        });
    }
    public int getDiscardedCount() {
        return guard.read(() -> discarded);
    }
    public int getTotal() {
        return guard.read(() -> discarded + recent.size());
    }
    public void flush() {
        guard.write(() -> {
            discarded += recent.size();
            recent.clear();
        });
    }
}
http://colobu.com/2014/11/06/secrets-of-java-8-lambda/
Brian Goetz是Oracle的Java语言架构师, JSR 335(Lambda Expression)规范的lead, 写了几篇Lambda设计方面的文章, 其中之一就是Translation of Lambda Expressions。 这篇文章介绍了Java 8 Lambda设计时的考虑以及实现方法。
他提到, Lambda表达式可以通过内部类, method handle, dynamic proxy等方式实现, 但是这些方法各有优劣。 真正要实现Lambda表达式, 必须兼顾两个目标: 一是不引入特定策略,以期为将来的优化提供最大的灵活性, 二是保持类文件格式的稳定。 通过Java 7中引入的invokedynamic (JSR 292), 可以很好的兼顾这两个目标。
invokedynamic 在缺乏静态类型信息的情况下可以支持有效的灵活的方法调用。主要是为了日益增长的运行在JVM上的动态类型语言, 如Groovy, JRuby。
invokedynamic将Lambda表达式的转换策略推迟到运行时, 这也意味着我们现在编译的代码在将来的转换策略改变的情况下也能正常运行。
编译器在编译的时候, 会将Lambda表达式的表达式体 (lambda body)脱糖(desugar) 成一个方法,此方法的参数列表和返回类型和lambda表达式一致, 如果有捕获参数, 脱糖的方法的参数可能会更多一些, 并会产生一个invokedynamic调用, 调用一个call site。 这个call site被调用时会返回lambda表达式的目标类型(functional interface)的一个实现类。 这个call site称为这个lambda表达式的lambda factory。 lambda factory的bootstrap方法是一个标准方法, 叫做lambda metafactory
编译器在转换lambda表达式时, 可以推断出表达式的参数类型,返回类型以及异常, 称之为natural signature, 我们将目标类型的方法签名称之为lambda descriptor, lambda factory的返回对象实现了函数式接口, 并且关联的表达式的代码逻辑, 称之为lambda object
  • 编译时
    • Lambda 表达式会生成一个方法, 方法实现了表达式的代码逻辑
    • 生成invokedynamic指令, 调用bootstrap方法, 由java.lang.invoke.LambdaMetafactory.metafactory方法实现
  • 运行时
    • invokedynamic指令调用metafactory方法。 它会返回一个CallSite, 此CallSite返回目标类型的一个匿名实现类, 此类关联编译时产生的方法
    • lambda表达式调用时会调用匿名实现类关联的方法。

https://vaadin.com/blog/-/blogs/no-need-to-wait-java-8-it-s-great


Labels

Review (572) System Design (334) System Design - Review (198) Java (189) Coding (75) Interview-System Design (65) Interview (63) Book Notes (59) Coding - Review (59) to-do (45) Linux (43) Knowledge (39) Interview-Java (35) Knowledge - Review (32) Database (31) Design Patterns (31) Big Data (29) Product Architecture (28) MultiThread (27) Soft Skills (27) Concurrency (26) Cracking Code Interview (26) Miscs (25) Distributed (24) OOD Design (24) Google (23) Career (22) Interview - Review (21) Java - Code (21) Operating System (21) Interview Q&A (20) System Design - Practice (20) Tips (19) Algorithm (17) Company - Facebook (17) Security (17) How to Ace Interview (16) Brain Teaser (14) Linux - Shell (14) Redis (14) Testing (14) Tools (14) Code Quality (13) Search (13) Spark (13) Spring (13) Company - LinkedIn (12) How to (12) Interview-Database (12) Interview-Operating System (12) Solr (12) Architecture Principles (11) Resource (10) Amazon (9) Cache (9) Git (9) Interview - MultiThread (9) Scalability (9) Trouble Shooting (9) Web Dev (9) Architecture Model (8) Better Programmer (8) Cassandra (8) Company - Uber (8) Java67 (8) Math (8) OO Design principles (8) SOLID (8) Design (7) Interview Corner (7) JVM (7) Java Basics (7) Kafka (7) Mac (7) Machine Learning (7) NoSQL (7) C++ (6) Chrome (6) File System (6) Highscalability (6) How to Better (6) Network (6) Restful (6) CareerCup (5) Code Review (5) Hash (5) How to Interview (5) JDK Source Code (5) JavaScript (5) Leetcode (5) Must Known (5) Python (5)

Popular Posts