🔏
Tech
  • 🟢App aspects
    • Software architecture
      • Caching
      • Anti-patterns
      • System X-ability
      • Coupling
      • Event driven architecture
        • Command Query Responsibility Segregation (CQRS)
        • Change Data Capture (CDC)
      • Distributed transactions
      • App dev notes
        • Architecture MVP
      • TEMP. Check list
      • Hexagonal arch
      • Communication
        • REST vs messaging
        • gRPC
        • WebSocket
      • Load balancers
      • Storage limits
      • Event storming
    • Authentication
    • Deployment strategy
  • Databases
    • Classification
    • DB migration tools
    • PostreSQL
    • Decision guidance
    • Index
      • Hash indexes
      • SSTable, LSM-Trees
      • B-Tree
      • Engines, internals
    • Performance
  • System design
    • Interview preparation
      • Plan
        • Instagram
        • Tinder
        • Digital wallet
        • Dropbox
        • Live video streaming
        • Uber
        • Whatsup
        • Tiktok
        • Twitter
        • Proximity service
    • Algorithms
    • Acronyms
  • 🟢Programming languages
    • Java
      • Features
        • Field hiding
        • HashCode() and Equals()
        • Reference types
        • Pass by value
        • Atomic variables
      • Types
      • IO / NIO
        • Java NIO
          • Buffer
          • Channel
        • Java IO: Streams
          • Input streams
            • BufferedInputStream
            • DataInputStream
            • ObjectInputStream
            • FilterInputStream
            • ByteArrayInputStream
        • Java IO: Pipes
        • Java IO: Byte & Char Arrays
        • Java IO: Input Parsing
          • PushbackReader
          • StreamTokenizer
          • LineNumberReader
          • PushbackInputStream
        • System.in, System.out, System.error
        • Java IO: Files
          • FileReader
          • FileWriter
          • FileOutputStream
          • FileInputStream
      • Multithreading
        • Thread liveness
        • False sharing
        • Actor model
        • Singleton
        • Future, CompletableFuture
        • Semaphore
      • Coursera: parallel programming
      • Coursera: concurrent programming
      • Serialization
      • JVM internals
      • Features track
        • Java 8
      • Distributed programming
      • Network
      • Patterns
        • Command
      • Garbage Collectors
        • GC Types
        • How GC works
        • Tools for GC
    • Kotlin
      • Scope functions
      • Inline value classes
      • Coroutines
      • Effective Kotlin
    • Javascript
      • Javascript vs Java
      • TypeScript
    • SQL
      • select for update
    • Python
  • OS components
    • Network
      • TCP/IP model
        • IP address in action
      • OSI model
  • 🟢Specifications
    • JAX-RS
    • REST
      • Multi part
  • 🟢Protocols
    • HTTP
    • OAuth 2.0
    • LDAP
    • SAML
  • 🟢Testing
    • Selenium anatomy
    • Testcafe
  • 🟢Tools
    • JDBC
      • Connection pool
    • Gradle
    • vim
    • git
    • IntelliJ Idea
    • Elastic search
    • Docker
    • Terraform
    • CDK
    • Argo CD
      • app-of-app setup
    • OpenTelemetry
    • Prometheus
    • Kafka
      • Consumer lag
  • 🟢CI
    • CircleCi
  • 🟢Platforms
    • AWS
      • VPC
      • EC2
      • RDS
      • S3
      • IAM
      • CloudWatch
      • CloudTrail
      • ELB
      • SNS
      • Route 53
      • CloudFront
      • Athena
      • EKS
    • Kubernetes
      • Networking
      • RBAC
      • Architecture
      • Pod
        • Resources
      • How to try
      • Kubectl
      • Service
      • Tooling
        • ArgoCD
        • Helm
        • Istio
    • GraalVM
    • Node.js
    • Camunda
      • Service tasks
      • Transactions
      • Performance
      • How it executes
  • 🟢Frameworks
    • Hibernate
      • JPA vs Spring Data
    • Micronaut
    • Spring
      • Security
      • JDBC, JPA, Hibernate
      • Transactions
      • Servlet containers, clients
  • 🟢Awesome
    • Нейробиология
    • Backend
      • System design
    • DevOps
    • Data
    • AI
    • Frontend
    • Mobile
    • Testing
    • Mac
    • Books & courses
      • Path: Java Concurrency
    • Algorithms
      • Competitive programming
    • Processes
    • Finance
    • Electronics
  • 🟢Electronics
    • Arduino
    • IoT
  • Artificial intelligence
    • Artificial Intelligence (AI)
  • 🚀Performance
    • BE
  • 📘Computer science
    • Data structures
      • Array
      • String
      • LinkedList
      • Tree
    • Algorithms
      • HowTo algorithms for interview
  • 🕸️Web dev (Frontend)
    • Trends
    • Web (to change)
  • 📈Data science
    • Time series
Powered by GitBook
On this page
  • Lambda expressions
  • Method references
  • Syntax
  • Constructor reference
  • Copy constructor
  • To Array
  • Functional interfaces
  • java.util.function
  • Stream
  • Create streams
  • Boxed streams
  • Reduction operations
  • Debugging streams with peak
  • Converting Strings to stream

Was this helpful?

  1. Programming languages
  2. Java
  3. Features track

Java 8

Lambda expressions

[optional] With explicit data types:

String[] names = directory.list((File dir, String name) -> name.endsWith(".java"));

Block syntax

String[] names = directory.list((File dir, String name) -> {
    return name.endsWith(".java")
});

Method references

Advantage over lambda:

  • shorter

  • includes the names of the class containing the method => easier to read

Syntax

  • object::instanceMethod (e.g. System.out::println, equivalent x -> System.out.println(x))

  • Class::staticMethod (e.g. Math::max, equivalent (x,y) -> Math.max(x,y))

  • Class::instanceMethod invoke a method on a reference to an object supplied by the context (e.g. String::length, equivalent x -> x.length())

Constructor reference

public class Person {
    private String name;
    
    public Person(){}
 
    public Person (String name) {
        this.name = name;
    }   
    // other methods
}    
List<Person> people = names.stream().map(Person::new).collect(Collectors.toList());

Based on the context in lambda expression => constructor with String arg is used.

Copy constructor

public Person (Person p) {
    this.name = p.name;
}
Person before = new Person("Before");
List<Person> people = Stream.of(before).collect(Collectors.toList());
Person after = people.get(0);

assertTrue(before == after);                 

before.setName("changed");
assertEquals("changed", after.getName());    

Using copy constructor it is possible to break that connection.

people = Stream.of(before).map(Person::new).collect(Collectors.toList());
Person after = people.get(0);

assertFalse(before == after);
assertEquals(before, after);

before.setName("changed");
assertFalse(before.equals(after));

To Array

People[] people = names.stream()
    .map(Person::new)            // constructor reference for Person
    .toArray(Person[]::new);     // constructor reference for array of Person       

Functional interfaces

@java.lang.FunctionalInterface        // provides compile-time check
public interface TheChecker {
    boolean check(String s);    // no need for abstract keyword
    // int anotherMethod();     // if added => not a functional interface any more
    
    default String sayHello() {
        return "Hello";
    }
    
    static void theStaticMethod() {
        System.out.println("I'm a static method in an interface");
    }
}

usage
TheChecker checker = new ConcreteChecker();
checker.sayHello();

all methods are public => no need to specify deliberately

// not a functional, because it has 2 abstract methods in total
public interface TheChild extends TheChecker {
    int bla();
}

Methods from Object don't count against the single abstract method limit (e.g. Comparator is still functional interface).

java.util.function

Consumer

void accept(T t)

default Consumer<T> andThen(Consumer<? super T> after)

How andThen method works:

v--- 1. c.accept("Java2s.com");        
c.andThen(c).andThen(c).accept("Java2s.com");
          ^          ^      
          |          |           
          |  3.  c.accept("Java2s.com");               
          |
2. c.accept("Java2s.com");  

Interface

single abstract method

IntConsumer

void accept(int x)

DoubleConsumer

void accept(double x)

LongConsumer

void accept(long x)

BiConsumer

void accept(T t, U u)

Supplier

T get()

Interface

Single abstract method

IntSupplier

int getAsInt()

DoubleSupplier

double getAsDouble()

LongSupplier

long getAsLong()

BooleanSupplier

boolean getAsBoolean()

Use case:

  • concept of deferred execution

public static void info(Logger logger, Supplier<String> message) {
  if (logger.isLoggable(Level.INFO))
      logger.info(message.get());
}

Predicate

boolean test(T t)
car.filter(cars, PREDICATE_IS_RED.or(PREDICATE_IS_FAST));

public List<Car> filter(List<Car> cars, Predicate<Car> pre);

Function

[Function<T,R>] R apply(T t)

Transforms input parameter of type T to output of type R

If (T == R) => UnaryOperator;

BiFunction

[BiFunction<T,U,R>] R apply(T t, U u)

if (R == T == U) => BinaryOperator (e.g. Math.max)

Stream

Stream is a sequence of elements that does not save elements or modify the original source

Streams do not process any data until a terminal expression is reached

long count = stream
  .map((value) -> { return value.toUpperCase(); }) // just listener is added. Non-terminal operation
  .map((value) -> { return value.substring(0,3); }) // just listener is added. Non-terminal operation
  .count(); // Terminal operation. Triggers stream processing.

Terminal operations: anyMatch(), allMatch(), noneMatch(), count(), collect(), findAny(), forEach(),...

Create streams

class Stream {
    
    @SafeVarargs
    public static<T> Stream<T> of(T... valuse) {
        return Arrays.stream(values);
    }
    
    // returns infinite sequential ordered stream
    static <T> Stream<T> iterate(T seed, UnaryOperator<T> f){}
    
    // produces sequential unordered stream by invoking Supplier
    static <T> Stream<T> generate(Supplier<T> s)
}
List<BigDecimal> nums =
    Stream.iterate(BigDecimal.ONE, n -> n.add(BigDecimal.ONE) )
        .limit(10)
        .collect(Collectors.toList());
System.out.println(nums);
// prints [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Stream.generate(Math::random) 
    .limit(10)
    .forEach(System.out::println)

IntStream, LongStream, DoubleStream

static IntStream range(int startInclusive, int endExclusive)
static IntStream rangeClosed(int startInclusive, int endInclusive)
static LongStream range(long startInclusive, long endExclusive) 
static LongStream rangeClosed(long startInclusive, long endInclusive)
List<Integer> ints = IntStream.range(10, 15)
    .boxed() // without boxed() DOES NOT COMPILE
    .collect(Collectors.toList());

Boxed streams

List<Integer> ints = IntStream.of(3, 1, 4, 1, 5, 9)
    .boxed() // to convert int to Integer for collection
    .collect(Collectors.toList());
List<Integer> ints = IntStream.of(3, 1, 4, 1, 5, 9)
    .mapToObj(Integer::valueOf)
    .collect(Collectors.toList())

Reduction operations

long count = Arrays.stream(strings)
        .map(String::length)
        .count();
        
int totalLength = Arrays.stream(strings) 
        .mapToInt(String::length)
        .sum();        
        
OptionalDouble ave = Arrays.stream(strings)
        .mapToInt(String::length)
        .average();
        
OptionalInt max = Arrays.stream(strings)
        .mapToInt(String::length)
        .max();                        

Reduce method:

OptionalInt reduce(IntBinaryOperator op)
int reduce(int identity, IntBinaryOperator op)

int sum = IntStream.rangeClosed(1, 10) 
    .reduce((x, y) -> x + y)
    .orElse(0);
// x - accumulator, y - value of the element in stream

int sum = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 
    .reduce(0, Integer::sum);
    
Stream.of("this", "is", "a", "list")
        .reduce("", String::concat); // thisisalist
        
Stream.of("this", "is", "a", "list")
        .collect(Collectors.joining());                

Most general form of reduce

<U> U reduce(U identity,
    BiFunction<U,? super T,U> accumulator,
    BinaryOperator<U> combiner)

Consider a Book class, the goal is to create a Map<Integer, Book> from List<Book>

public class Book { 
    private Integer id; 
    private String title;
}

books.stream()
    .reduce(new HashMap<Integer,Book>(),     // collect to
            (map, book) -> {        // how to add one element
                map.put(book.getId(), book);
                return map:
            },    
            (map1, map2) -> {       // how to compibe two maps. Needed for multithreading     
                map1.putAll(map2);
                return map1;
            });    

Debugging streams with peak

Stream<T> peek(Consumer<? super T> action)

returns a stream consisting of the elements of this stream, additionally performing the provided action on each element as they are consumed from the resulting stream.

Converting Strings to stream

String implements CharSequence, it means

public default IntStream chars() {...}
public default IntStream codePoints() {...}

PreviousFeatures trackNextDistributed programming

Last updated 1 year ago

Was this helpful?

Useful if you want to isolate original instances.

You can have a method which has a parameter of Predicate type.

Can be a good idea to have frequently used predicates as a constants.

It is possible to combine predicates using default methods:

🟢
💡
💡
💡
💡