JDK8: encounter of eight kind


@ladislavGazo

gazo@seges.sk


JDK6

(2006 - 2015)

But what were the features?

  • Collections framework
  • Deployment
  • Drag and drop
  • Instrumentation
  • Internationalization support
  • I/O support
  • ... blah blah blah


Boring stuff

+ performance improvements









x -> x + 1           





 Function<Integer, Integer> add = x -> x + 1;





Integer result = add.apply(4);

And what if one exists?




       Function<Integer, Integer> add = MathUtils::add;


java.util.function


notable:

  • Consumer<T>
    • R accept(T)
  • Supplier<R>
    • R get()
  • Predicate<T>
    • boolean test(T), and, or,...
  • BiFunction
  • BiConsumer
  • ...


EX: Functional Setting


- calculate current user and if not empty, set it

- without object hell

- not to repeat everywhere this:

String username = Session.getCurrentUsername();
if(username != null || !username.isEmpty()) {
    map.put(key, username);
} 

and again, but different

String username = Session.getCurrentUsername();
if(username != null || !username.isEmpty()) {
    manager.call(username);
} 

WHAT about this?




securityManager.setCurrentUsername(
    user -> variables.put(ProcessVariableConstant.USERNAME, user)
); 


First Iteration

reminds OO-approach a bit

public class SecurityManager {
    ...

    public void setCurrentUsername(VoidFunction f) {
        String username = getCurrentUsername();
        if(username != null || !username.isEmpty()) {
            f.run(username);
        }
    }

    @FunctionalInterface
    public interface VoidFunction {
        void run(T input);
    }
}

Functional Sugar


public class SecurityManager {
    ...

    public void setCurrentUsername(Consumer f) {
        String username = getCurrentUsername();
        if(username != null || !username.isEmpty()) {
            f.accept(username);
        }
    }
} 



Optionals


  • for avoiding NPEs where possible
  • use:
    • as return type of function
  • not as:
    • method || constructor parameter
    • model objects






    Optional<Integer> userId = repository.findOne("john");




Initialization



Optional opt = Optional.of(nonNullInteger);

Optional opt = Optional.ofNullable(possiblyNullInteger);

Optional empty = Optional.empty();


Handy Usage


if ( opt.isPresent() ) {
  service.store(opt.orElse(new UserAccount()));
}

or more functional

opt.ifPresent( obj -> service.store(obj.get()) );




TRANSFORMATION


List<FormProcessDefinition> processDefinitions = form.getProcessDefinitions();

a.k.a. MAP

processDefinitions.stream().map((definition) -> {
        
ProcessDefinition processDefinition = new ProcessDefinition();
processDefinition.setKey(definition.getKey());
processDefinition.setName(definition.getName()); return processDefinition;
}).collect(Collectors.toList());

For each as stream???



Set<String> roleSystemNames = getRequiredRoleNames();
        
roleSystemNames. forEach(roleSystemName -> { ... });

or if function exists for that

Set roleSystemNames = getRequiredRoleNames();
roleSystemNames.forEach(service::store);   

& sometimes it's unreadable



Map jsonVariables = variables.entrySet().stream().map(
entry -> new AbstractMap.SimpleEntry(
entry.getKey(),
 createTypedValue(entry.getValue())
)
).collect(
Collectors.toMap(
e -> ((AbstractMap.SimpleEntry) e).getKey(),
e -> ((AbstractMap.SimpleEntry) e).getValue()
)
);

For simple For-each



Map<String, JSONObject> jsonVariables = new HashMap<>();

variables.forEach((k, v) -> {
jsonVariables.put(k, createTypedValue(v));
});



but maybe for parallel processing

Stream will be more efficient

!

FILES

with streams

=

more pleasure


 Files.list(new File(".").toPath())
.filter(p -> !p.getFileName().toString().startsWith("."))
.limit(3)
.forEach(System.out::println);


... and reduce ... and limit example

FILE PROCESSING is scary


try {

  FileInputStream fstream = new FileInputStream("textfile.txt");

  DataInputStream in = new DataInputStream(fstream);
  BufferedReader br = new BufferedReader(new InputStreamReader(in));
  String strLine;

  while ((strLine = br.readLine()) != null)   {
    ...
  }

  in.close();

}catch (Exception e) {
  ...
}

... Not anymore



try (Stream<String> stream = Files.lines(Paths.get("my.json"))) {
stream
.filter(line -> line.contains("name"))
.map(String::trim)
.forEach(System.out::println);
}


... with automatic file closing ...





Strings & Patterns

String.join(":","Java","Group","2015");

// Java:Group:2015

Pattern pattern = Pattern.compile(".*@seges\\.sk");

Stream.of("gazo@seges.sk", "john@hotmail.com")
    .filter(pattern.asPredicate())
    .count();

// 1

Pattern.compile(";")
    .splitAsStream("javagroup;java;group")
    .filter(s -> s.contains("group"))
    .sorted()
    .collect(Collectors.joining(":"));
// => group:javagroup


SQL Parallels






Questions?





@ladislavGazo
gazo@seges.sk

JDK8 encounter of eight kind

By lgazo

JDK8 encounter of eight kind

How the change from JDK6 enlightens developers when they face JDK8 functional approach.

  • 1,146