Saturday, October 21, 2017

Java 8 Stream, Collectors Examples


Here are the examples of the Java 8 Stream

Methods in Stream interface

collect, forEach, filter, flatMap,  flatMapToInt, limit, map, mapToInt, of, parallel, peek, reduce, stream.

flatMap: a set of collections is required to produce the final flattered collection.
parallel: a set of collections is required to run the combiner function.
peek: very useful for debugging.
collect and reduce: there are Collectors class that provides many convenient methods.

Methods in Collectors

averagingDouble, groupBy, partitionBy, toMap, toList, toSet.



import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.Set;
import java.util.TreeMap;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.junit.Test;

public class StreamExamples {
       static List<Employee> employeeList = Arrays.asList(new Employee("Tom Jones", 45, "A"),
                    new Employee("Harry Major", 25, "B"), new Employee("Ethan Hardy", 65, "A"),
                    new Employee("Nancy Smith", 15, "C"), new Employee("Deborah Sprightly", 29, "A"));

       @Test
       public void testFlatMapAndPeek() {
             List<String> originalStringList = Arrays.asList("Peter", "Adam", "John");
             Stream<String> a = originalStringList.stream();
             // Object array is required, s.split("") returns a String[], primitive
             // arrays such as char[] do not work here.
             Stream<String[]> b = a.map(s -> s.split("")).peek(s -> System.out.println(Arrays.toString(s)));
             Stream<String> d = b.flatMap(c -> Arrays.stream(c));
             Optional<String> e = d.limit(10).reduce((s1, s2) -> s1 + s2);
             System.out.println(e.get());
       }

       @Test
       public void testFlatMapAndFilterAndCount() {
             long count = Stream.of("Adam", "Peter", "Mike", "alice", "Linda", "pam").map(s -> s.toUpperCase())
                           .filter(s -> s.startsWith("A")).map(s -> s.split("")).flatMap(s -> Arrays.stream(s)).count();
             System.out.println("count:" + count);

             employeeList.stream().map(emp -> emp.getName()).forEach(System.out::println);
             employeeList.stream().map(emp -> emp.getName().split("")).flatMap(array -> Arrays.stream(array))
                           .map(str -> str.toUpperCase()).filter(str -> !(str.equals(" ")))
                           .forEach(str -> System.out.println(str));
       }

       @Test
       public void testMapToIntAndSum() {
             Stream<Integer> stream = Stream.of(1, 2, 3, 4);
             int sum = stream.filter(i -> i > 1).mapToInt(i -> i).sum();
             System.out.println("sum:" + sum);
       }

       @Test
       public void testStreamWithPrimitiveChar() {
             List<String> strList = new ArrayList<>();
             strList.add("Peter");
             strList.add("Jane");
             int[] ci = strList.stream().map(s -> s.chars()).flatMapToInt(i -> i).toArray();
             for (int c : ci) {
                    System.out.println((char) c);
             }
       }

       @Test
       public void testReduce() {
             System.out.println("===testReduce===");
             String r = Stream.of("Peter", "Jane").map(s -> s.split("")).flatMap(s -> Arrays.stream(s))
                           .peek(System.out::println).reduce("s", (a, b) -> a + b);
             System.out.println("r:" + r);

             OptionalInt sum = Stream.of("Peter", "Jane").map(s -> s.chars()).flatMapToInt(i -> i).peek(System.out::println)
                           .reduce((i, j) -> {
                                 return i + j;
                           });
             System.out.println("sum:" + sum.getAsInt());

             String reduced = Stream.of("123", "456").parallel().map(s -> s.split("")).flatMap(i -> Arrays.stream(i))
                           .peek(System.out::println).reduce("s", (i, j) -> i + ":" + j, (k, l) -> k + ";" + l);
             System.out.println("reduced:" + reduced);

             int reduced1 = Stream.of("123", "456").parallel().map(s -> s.split("")).flatMap(i -> Arrays.stream(i))
                           .peek(System.out::println).reduce(0, (i, j) -> i + Integer.parseInt(j), (k, l) -> k * l);
             System.out.println("reduced1:" + reduced1);
       }

       @Test
       public void testFunctionInterfaces() {
             Function<List<String>, List<String>> toUppderCase = a -> a.stream().map(s -> s.toUpperCase())
                           .collect(Collectors.toList());
             Function<List<String>, List<String>> filter = a -> a.stream().filter(s -> s.startsWith("A"))
                           .collect(Collectors.toList());
             Function<List<String>, StringBuilder> accumulateResult = a -> a.stream().collect(StringBuilder::new,
                           (response, element) -> response.append(" ").append(element),
                           (response1, response2) -> response1.append(",").append(response2.toString()));

             Function<List<String>, StringBuilder> f = toUppderCase.andThen(filter).andThen(accumulateResult);
              System.out.println("##############################################");
             System.out.println(f.apply(Arrays.asList("Adam", "Peter", "Mike", "alice", "Linda", "pam")));
       }

       @Test
       public void testCollectors() {
             System.out.println("===testCollectors===");
             String joinedResult = Stream.of("Adam", "Peter", "Mike", "alice", "Linda", "pam").map(s -> s.toUpperCase())
                           .filter(s -> s.startsWith("A")).collect(Collectors.joining(",", "name:[", "]"));
             System.out.println("joinedResult:" + joinedResult);

             Map<Integer, List<String>> a = Stream.of("Adam", "Peter", "Mike", "alice", "Linda", "pam")
                           .map(s -> s.toUpperCase()).collect(Collectors.groupingBy(String::length));
             System.out.println("groups:" + a);

             Map<String, List<Employee>> b = employeeList.stream().collect(Collectors.groupingBy(e -> e.getDepartment()));
             System.out.println("groups:" + b);

             Map<String, Set<String>> c = employeeList.stream().collect(Collectors.groupingBy(Employee::getDepartment,
                           TreeMap::new, Collectors.mapping(Employee::getName, Collectors.toSet())));
             System.out.println("groups:" + c);

             Double averageAge = employeeList.stream().collect(Collectors.averagingDouble(e -> e.getRate()));
             System.out.println("averageAge:" + averageAge);

             Map<Boolean, List<Employee>> d = employeeList.stream()
                           .collect(Collectors.partitioningBy(e -> e.getRate() > 30));
             System.out.println("groups:" + d);

             Map<Boolean, Set<String>> f = employeeList.stream().collect(Collectors.partitioningBy(e -> e.getRate() > 30,
                           Collectors.mapping(e -> e.getName(), Collectors.toSet())));
             System.out.println("groups:" + f);

             Map<String, String> g = employeeList.stream()
                           .collect(Collectors.toMap(e -> e.getDepartment(), e -> e.getName(), (a1, a2) -> a1 + "," + a2));
             System.out.println("groups:" + g);
       }

       @Test
       public void testCollectAndParallel() {
             StringBuilder result = Stream.of("Adam", "Peter", "Mike", "alice", "Linda", "pam").map(s -> s.toUpperCase())
                           .collect(StringBuilder::new, (stringBuilder, s) -> {
                                 int i = stringBuilder.length();
                                 if (i == 0) {
                                        stringBuilder.append(s);
                                 } else {
                                        stringBuilder.append("/").append(s);
                                 }
                           }, (response1, response2) -> response1.append(",").append(response2.toString()));
             System.out.println("result of non-parallel run:" + result);

             String result2 = Stream
                           .of(Arrays.asList("Adam", "Alan"), Arrays.asList("Peter", "Pam"),
                                        Arrays.asList("Mike", "alice", "Linda"))
                           .parallel().flatMap(s -> s.stream()).collect(StringBuilder::new, (stringBuilder, s) -> {
                                 int i = stringBuilder.length() + 1;
                                 if (i == 0) {
                                        stringBuilder.append(s);
                                 } else {
                                        stringBuilder.append("/").append(s);
                                 }
                           }, (response1, response2) -> response1.append(",").append(response2.toString())).toString();
             System.out.println("result of parallel run:" + result2);

       }

       public static class Employee {
             @Override
             public String toString() {
                    return "Employee [name=" + name + ", rate=" + rate + ", department=" + department + "]";
             }

             private final String name;
             private final Integer rate;
             private final String department;

             public Employee(final String name, final Integer rate, final String department) {
                    this.name = name;
                    this.rate = rate;
                    this.department = department;
             }

             public String getName() {
                    return name;
             }

             public Integer getRate() {
                    return rate;
             }

             public String getDepartment() {
                    return department;
             }
       }
}


Friday, October 20, 2017

JBoss EAP 6.x Configurations


In JBoss EAP 6.4, the following is the list of the most commonly used configuration files:

in the bin directory:

standalone.sh 

(OS related script)

standalone.conf 

(Java start up parameters)

in the standalone/configuration:

standalone.xml

Structure:
extensions - extension - module
system-properties
management - security-realms
prifile - sub-systems
interface
socket-binding-groups

Dependency control in application:

jboss-deployment-structure.xml

deployment
exclude-subsystems
subsystem
exclusions
module
dependencies
module


Thursday, October 19, 2017

Java Annotation, Reflection and Inheritance

Annotation

Annotation is most commonly used to store extra information in classes that could be used at runtime by frameworks.

An annotation is defined as meta-data type. attributes could be added to store specific values when the annotation is used.

Reflection

Frameworks use the Java reflection to retrieve annotations.

Inheritance

Annotation Subclass

It is not possible to extend an annotation to create a annotation type hierarchy. However a new annotation could be created to substitute an annotation with specific attribute values when it is used frequently. Or a new annotation could be used to represent multiple annotations if they are frequently used together.

such as:

@Category(value="Food")
public @interface FoodCategory {}

@Action1
@Action2
@Action3
public @interface ActionGroup1 {}


Annotation Type Declaration Inheritance

If the @Inherited annotation is used, the Annotation declaration is inherited in class hierarchy only. The annotation declaration on an interface is not inherited.

However, the Annotations declared on interfaces are able to be used by their sub types by using reflection to search its type hierarchy. If the interfaces are searched, it is going to be a tree search!

Here are some tests that demo the usages of get annotations in type hierarchies through reflection:



@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Inherited
public @interface MyAnnotation {
       String name();
       String value();
}

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@MyAnnotation(name = "usage", value = "extends")
public @interface MyAnnotationExt {
       String name();
       String value();
}

public class AnnotationUsages {

       @MyAnnotation(name = "name1", value = "value1")
       public void getAnnotation() {
             try {
                    Class<? extends AnnotationUsages> cls = this.getClass();
                    Method method = cls.getMethod("getAnnotation");
                    MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
                    System.out.println(myAnnotation);
             } catch (SecurityException | NoSuchMethodException e) {
                    e.printStackTrace();
             }
       }

       @MyAnnotationExt(name = "name2", value = "value2")
       public void getAnnotationOfAnnotation() {
             try {
                    Class<? extends AnnotationUsages> cls = this.getClass();
                    Method mth = cls.getMethod("getAnnotationOfAnnotation");
                    Annotation[] annotations = mth.getAnnotations();
                    for (Annotation annotation : annotations) {
                           System.out.println(annotation.toString());
                    }
                    MyAnnotationExt myAnnotationExt = mth.getAnnotation(MyAnnotationExt.class);
                    annotations = myAnnotationExt.annotationType().getAnnotations();
                    for (Annotation annotation : annotations) {
                           System.out.println(annotation.toString());
                    }
             } catch (SecurityException | NoSuchMethodException e) {
                    e.printStackTrace();
             }
       }

       // Annotations over annotation

       @Test
       public void testMethodAnnotations() {
             AnnotationUsages usages = new AnnotationUsages();
             usages.getAnnotation();
             usages.getAnnotationOfAnnotation();
       }

       // Annotations over type hierarchy

       @Test
       public void testTypeAnnotations() {
             MyClass1 cls1 = new MyClass1();
             cls1.getTypeAnnotation();
             MyClass2 cls2 = new MyClass2();
             cls2.getTypeAnnotation();
             MyClass3 cls3 = new MyClass3();
             cls3.getTypeAnnotation();
             MyInterface myInterfaceInstance = new MyClass3();
             System.out.println("===MyInterface===");
             try {
                    Class<?> myInterface = myInterfaceInstance.getClass().getInterfaces()[0];
                    Annotation[] annotations = myInterface.getAnnotations();
                    for (Annotation annotation : annotations) {
                           System.out.println(annotation.toString());
                    }
             } catch (SecurityException e) {
                    e.printStackTrace();
             }
       }

       @MyAnnotation(name = "name1", value = "value1")
       @MyAnnotationExt(name = "name2", value = "value2")
       interface MyInterface {
             public void getTypeAnnotation();
       }

       @MyAnnotation(name = "name10", value = "value10")
       @MyAnnotationExt(name = "name20", value = "value20")
       public static class MyClass1 {
             public void getTypeAnnotation() {
                    try {
                           System.out.println("===MyClass1===");
                           Class<? extends MyClass1> cls = this.getClass();
                           Annotation[] annotations = cls.getAnnotations();
                           for (Annotation annotation : annotations) {
                                 System.out.println(annotation.toString());
                           }
                    } catch (SecurityException e) {
                           e.printStackTrace();
                    }
             }
       }

       public static class MyClass2 extends MyClass1 {
             @Override
             public void getTypeAnnotation() {
                    System.out.println("===MyClass2===");
                    try {
                           Class<? extends MyClass2> cls = this.getClass();
                           Annotation[] annotations = cls.getAnnotations();
                           for (Annotation annotation : annotations) {
                                 System.out.println(annotation.toString());
                           }
                    } catch (SecurityException e) {
                           e.printStackTrace();
                    }
             }
       }

       public static class MyClass3 implements MyInterface {
             @Override
             public void getTypeAnnotation() {
                    System.out.println("===MyClass3===");
                    try {
                           Class<? extends MyClass3> cls = this.getClass();
                           Annotation[] annotations = cls.getAnnotations();
                           for (Annotation annotation : annotations) {
                                 System.out.println(annotation.toString());
                           }
                    } catch (SecurityException e) {
                           e.printStackTrace();
                    }
             }
       }
}





 The results:


@com.americanexpress.ssae.sample.annotation.MyAnnotation(name=name1, value=value1)
@com.americanexpress.ssae.sample.annotation.MyAnnotationExt(name=name2, value=value2)
@java.lang.annotation.Retention(value=RUNTIME)
@java.lang.annotation.Target(value=[TYPE, METHOD, PARAMETER, FIELD, ANNOTATION_TYPE])
@com.americanexpress.ssae.sample.annotation.MyAnnotation(name=usage, value=extends)

===MyClass1===
@com.americanexpress.ssae.sample.annotation.MyAnnotation(name=name10, value=value10)
@com.americanexpress.ssae.sample.annotation.MyAnnotationExt(name=name20, value=value20)
===MyClass2===
@com.americanexpress.ssae.sample.annotation.MyAnnotation(name=name10, value=value10)
===MyClass3===
===MyInterface===
@com.americanexpress.ssae.sample.annotation.MyAnnotation(name=name1, value=value1)
@com.americanexpress.ssae.sample.annotation.MyAnnotationExt(name=name2, value=value2)