Introduction to Spliterator in Java 8 Stream

Introduction to the

Spliterator is an interface introduced in Java 8 that is often used with stream to iterate over and split sequences.

Spliterators are needed wherever a stream is used, such as a List, Collection, IO channel, etc.

Let’s first look at the stream method definition in Collection:

default Stream<E> stream(a) {
        return StreamSupport.stream(spliterator(), false);
    }
Copy the code
default Stream<E> parallelStream(a) {
        return StreamSupport.stream(spliterator(), true);
    }
Copy the code

As you can see, both parallel and non-parallel streams are constructed through StreamSupport and require a spliterator argument.

Now that we know what spliterator does, let’s look at its structure:

Spliterator has four methods that must be implemented, which we’ll cover in detail next.

tryAdvance

TryAdvance is a method that processes elements in a stream, processing them if they exist and returning true, otherwise returning false.

If we do not want to process subsequent elements of the stream, we simply return false in the tryAdvance. Using this feature, we can interrupt stream processing. This is an example that I will cover in a later article.

trySplit

TrySplit is an attempt to split existing streams. It is commonly used in parallel streams where multiple threads are needed to handle the different elements of a stream. TrySplit is a method of splitting elements of a stream.

Ideally, trySplit should split the stream into two equal numbers to maximize performance.

estimateSize

EstimateSize represents the elements to be processed in Spliterator, and is generally different before and after trySplit, as we’ll explain in the examples below.

characteristics

Characteristics The Spliterator has eight characteristics:

public static final int ORDERED    = 0x00000010;// Indicates that the elements are ordered (the result is the same each time)
public static final int DISTINCT   = 0x00000001;// indicates that the element is not repeated
public static final int SORTED     = 0x00000004;// Indicates that the elements are arranged in a regular way (with specified comparators)
public static final int SIZED      = 0x00000040;//It means the size is fixedpublic static final int NONNULL    = 0x00000100;// Indicates no null elements
public static final int IMMUTABLE  = 0x00000400;// The element is immutable
public static final int CONCURRENT = 0x00001000;// indicates that iterators can be multithreaded
public static final int SUBSIZED   = 0x00004000;// Indicates that all child Spliterators have the SIZED feature
Copy the code

A Spliterator can have multiple features, which can be characterized by or calculation.

For example

We’ve discussed some of the key Spliterator methods above, but let’s take a concrete example:

@AllArgsConstructor
@Data
public class CustBook {
    private String name;

}
Copy the code

Start by defining a CustBook class with a name variable.

Define a method to generate a list of CUSTbooks:

    public static List<CustBook> generateElements(a) {
        return Stream.generate(() -> new CustBook("cust book"))
                .limit(1000)
                .collect(Collectors.toList());
    }
Copy the code

We define a call method in which the tryAdvance method is called, passing in our custom processing method. Here we modify the name of book and attach additional information.

    public String call(Spliterator<CustBook> spliterator) {
        int current = 0;
        while (spliterator.tryAdvance(a -> a.setName("test name"
                .concat("- add new name")))) {
            current++;
        }

        return Thread.currentThread().getName() + ":" + current;
    }
Copy the code

Finally, write the test method:

    @Test
    public void useTrySplit(a){
        Spliterator<CustBook> split1 = SpliteratorUsage.generateElements().spliterator();
        Spliterator<CustBook> split2 = split1.trySplit();

        log.info("before tryAdvance: {}",split1.estimateSize());
        log.info("Characteristics {}",split1.characteristics());
        log.info(call(split1));
        log.info(call(split2));
        log.info("after tryAdvance {}",split1.estimateSize());
    }
Copy the code

The results are as follows:

23:10:08. [the main] INFO 852 com. Flydean. SpliteratorUsage - before tryAdvance: 500 23:10:08. [the main] INFO 857 com. Flydean. SpliteratorUsage - 16464 23:10:08 Characteristics. [the main] 858 INFO Com. Flydean. SpliteratorUsage - the main: 500 23:10:08. 858 [main] INFO com. Flydean. SpliteratorUsage - the main: 500 23:10:08. 858 [main] INFO com.flydean.SpliteratorUsage - after tryAdvance 0Copy the code

The List has a total of 1000 pieces of data, and after a call to trySplit, the List is split into two parts with 500 pieces of data each.

Notice that after the tryAdvance call, estimateSize changes to 0, indicating that all elements have been processed.

Characteristics=16464, convert to hexadecimal: Ox4050 = ORDERED or SIZED or subsidzed The OR operation.

This is also a fundamental feature of ArrayLists.

conclusion

Spliterator: Spliterator: Spliterator: Spliterator: Spliterator: Spliterator: Spliterator: Spliterator: Spliterator: Spliterator: Spliterator: Spliterator

Examples of this article github.com/ddean2009/l…

Welcome to pay attention to my public number: procedures those things, more wonderful waiting for you! For more, visit www.flydean.com