How to do it...

Follow these steps to implement the example:

  1. Create a class named Item to store the information of each element of the matrix. It will have three private attributes: a String attribute named name and two integer attributes named row and column. Create the methods to get and set the values of these attributes. The code of this class is very simple, so it won't be included here.
  2. Create a class named MySpliterator. Specify that it implements the Spliterator interface parameterized by the Item class. This class has four attributes: a matrix of Item objects named items and three integer attributes named start, end, and current to store the first and last elements that will be processed by this Spliterator interface and the current element that is being processed. Implement the constructor of the class to initialize all these attributes:
        public class MySpliterator implements Spliterator<Item> { 

private Item[][] items;
private int start, end, current;

public MySpliterator(Item[][] items, int start, int end) {
this.items=items;
this.start=start;
this.end=end;
this.current=start;
}
  1. Implement characteristics(). This method will return an int value that describes the behavior of Spliterator. The meaning of this value will be explained later in the How it Works... section:
        @Override 
public int characteristics() {
return ORDERED | SIZED | SUBSIZED;
}
  1. Implement estimatedSize(). This method will return the number of elements to be processed by this Spliterator. We will calculate it as the difference between the end and current attributes:
        @Override 
public long estimateSize() {
return end - current;
}
  1. Now implement tryAdvance(). This method will be called to try and process an element of the Spliterator. The input parameter of the tryAdvance() method is and object that implements the Consumer interface. It will be called by the Stream API, so we only have to worry about its implementation. In our case, as mentioned in the introduction to this chapter, we have a matrix of Item objects and we're going to process a row each time. The Consumer function received will process an Item object. Therefore, if the Spliterator interface still has elements to process, we will process all the items of the current row using the accept() method of the Consumer function:
        @Override 
public boolean tryAdvance(Consumer<? super Item> consumer) {
System.out.printf("MySpliterator.tryAdvance.start: %d, %d, %d ",
start,end,current);
if (current < end) {
for (int i=0; i<items[current].length; i++) {
consumer.accept(items[current][i]);
}
current++;
System.out.printf("MySpliterator.tryAdvance.end:true ");
return true;
}
System.out.printf("MySpliterator.tryAdvance.end:false ");
return false;
}
  1. Now implement forEachRemaining(). This method will receive an implementation of the Consumer interface and will apply this function to the remaining elements of Spliterator. In our case, we will call the tryAdvance() method for all the remaining elements:
        @Override 
public void forEachRemaining(Consumer<? super Item> consumer) {
System.out.printf("MySpliterator.forEachRemaining.start ");
boolean ret;
do {
ret=tryAdvance(consumer);
} while (ret);
System.out.printf("MySpliterator.forEachRemaining.end ");
}
  1. Finally, implement trySplit(). This method will be called by parallel streams to split Spliterator into two subsets. It will return a new Spliterator object with the elements that will be processed by another thread. The current thread will process the rest of the elements. If the spliterator object can't be split, you have to return a null value. In our case, we will calculate the element in the middle of the elements we have to process. The first half will be processed by the current thread, and the second half will be processed by another thread:
        @Override 
public Spliterator<Item> trySplit() {
System.out.printf("MySpliterator.trySplit.start ");

if (end-start<=2) {
System.out.printf("MySpliterator.trySplit.end ");
return null;
}
int mid=start+((end-start)/2);
int newStart=mid;
int newEnd=end;
end=mid;
System.out.printf("MySpliterator.trySplit.end: %d, %d, %d,
%d, %d, %d ",start, mid, end, newStart,
newEnd, current);

return new MySpliterator(items, newStart, newEnd);
}
  1. Now implement the Main class of the project with the main() method. First, declare and initialize a matrix with 10 rows and 10 columns of Item objects:
        public class Main { 

public static void main(String[] args) {
Item[][] items;
items= new Item[10][10];

for (int i=0; i<10; i++) {
for (int j=0; j<10; j++) {
items[i][j]=new Item();
items[i][j].setRow(i);
items[i][j].setColumn(j);
items[i][j].setName("Item "+i+" "+j);
}
}
  1. Then, create a MySpliterator object to process all the elements of the matrix:
        MySpliterator mySpliterator=new MySpliterator(items, 0,
items.length);
  1. Finally, use the stream() method of the StreamSupport class to create a stream from Spliterator. Pass the true value as the second parameter to indicate that our stream will be in parallel. Then, use the forEach() method of the Stream class to write information about each element:
          StreamSupport.stream(mySpliterator, true).forEach( item -> { 
System.out.printf("%s: %s ",Thread.currentThread()
.getName(),item.getName());
});
}
..................Content has been hidden....................

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