How to do it...

Follow these steps to implement the example:

  1. Create a class named Person. This class will have six attributes to define some basic characteristics of a person. We will implement the methods to get() and set() the values of the attributes, but they won't be included here:
        public class Person { 
private int id;
private String firstName;
private String lastName;
private Date birthDate;
private int salary;
private double coeficient;
  1. Now, implement a class named PersonGenerator. This class will only have a method named generatedPersonList() to generate a list of Person objects with random values with the size specified in parameters. This is the source code of this class:
        public class PersonGenerator { 
public static List<Person> generatePersonList (int size) {
List<Person> ret = new ArrayList<>();

String firstNames[] = {"Mary","Patricia","Linda",
"Barbara","Elizabeth","James",
"John","Robert","Michael","William"};
String lastNames[] = {"Smith","Jones","Taylor",
"Williams","Brown","Davies",
"Evans","Wilson","Thomas","Roberts"};

Random randomGenerator=new Random();
for (int i=0; i<size; i++) {
Person person=new Person();
person.setId(i);
person.setFirstName(firstNames
[randomGenerator.nextInt(10)]);
person.setLastName(lastNames
[randomGenerator.nextInt(10)]);
person.setSalary(randomGenerator.nextInt(100000));
person.setCoeficient(randomGenerator.nextDouble()*10);
Calendar calendar=Calendar.getInstance();
calendar.add(Calendar.YEAR, -randomGenerator
.nextInt(30));
Date birthDate=calendar.getTime();
person.setBirthDate(birthDate);

ret.add(person);
}
return ret;
}
}
  1. Now, implement a task named PersonMapTask. The main purpose of this task will be to convert a list of persons on a map, where the keys will be the name of the persons and the values will be a list with Person objects whose name is equal to the key. We will use the fork/join framework to implement this transformation, so the PersonMapTask  will extend the RecursiveAction class:
        public class PersonMapTask extends RecursiveAction {
  1. The PersonMapTask class will have two private attributes: List of Person objects to process and ConcurrentHashMap to store results. We will use the constructor of the class to initialize both the attributes:
        private List<Person> persons; 
private ConcurrentHashMap<String, ConcurrentLinkedDeque
<Person>> personMap;

public PersonMapTask(List<Person> persons, ConcurrentHashMap
<String, ConcurrentLinkedDeque<Person>> personMap) {
this.persons = persons;
this.personMap = personMap;
}
  1. Now it's time to implement the compute() method. If the list has less than 1,000 elements, we will process the elements and insert them in ConcurrentHashMap. We will use the computeIfAbsent() method to get List associated with a key or generate a new ConcurrentMapedDeque object if the key doesn't exist in the map:
        protected void compute() { 

if (persons.size() < 1000) {

for (Person person: persons) {
ConcurrentLinkedDeque<Person> personList=personMap
.computeIfAbsent(person.getFirstName(), name -> {
return new ConcurrentLinkedDeque<>();
});
              personList.add(person); 
}
return;
}
  1. If List has more than 1,000 elements, we will create two child tasks and delegate the process of a part of the list to them:
          PersonMapTask child1, child2; 

child1=new PersonMapTask(persons.subList(0,persons.size()/2),
personMap);
child2=new PersonMapTask(persons.subList(persons.size()/2,
persons.size()),
personMap);

invokeAll(child1,child2);
}
}
  1. Finally, implement the Main class with the main() method. First, generate a list with 100,000 random Person objects:
        public class Main { 

public static void main (String[] args) {
List<Person> persons=PersonGenerator
.generatePersonList(100000);
  1. Then, compare two methods to generate Map with the names as keys, which are part of List, and Person as value. List will use a parallel Stream function and the collect() method using the groupingByConcurrent() collector:
        Date start, end; 

start = new Date();
Map<String, List<Person>> personsByName = persons
.parallelStream()
.collect(Collectors.groupingByConcurrent(p -> p
.getFirstName()));
end = new Date();
System.out.printf("Collect: %d - %d ", personsByName.size(),
end.getTime()-start.getTime());
  1. The second option is using the fork/join framework and the PersonMapTask class:
            start = new Date(); 
ConcurrentHashMap<String, ConcurrentLinkedDeque<Person>>
forkJoinMap=new ConcurrentHashMap<>();
PersonMapTask personMapTask=new PersonMapTask
(persons,forkJoinMap);
ForkJoinPool.commonPool().invoke(personMapTask);
end = new Date();

System.out.printf("Collect ForkJoinPool: %d - %d ",
forkJoinMap.size(),
end.getTime()-start.getTime());
}
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.225.72.245