JAVA 8 Spliterator

1.Spliterator是Java 8中加入的另一个新接口;这个名字代表“可分迭代器”(splitable iterator)。和Iterator一样,Spliterator也用于遍历数据源中的元素,但它是为了并行执行 而设计的 .Java 8已经为集合框架中包含的所有数据结构提供了一个 默认的Spliterator实现,

集合实现了Spliterator接口,接口提供了一个spliterator方法。 这个接口定义了若干方法

public interface Spliterator<T> {    

boolean tryAdvance(Consumer<? super T> action);    

Spliterator<T> trySplit();  

  long estimateSize();  

  int characteristics(); }

tryAdvance方法的行为类似于普通的Iterator ,因为它会按照顺序一个个使用 Spliterator的元素,,并且如果还有其他元素要遍 历就返回true。但 trySplit是专为Spliterator接口设计的,因为它可以把一些元素划出去分 给第二个Spliterator(由该方法返回),让它们两个并行处理。Spliterator还可通过 estimateSize方法估计还剩下多少元素要遍历,因为即使不那么确切,能快速算出来是一个值 也有助于让拆分均匀一点

characteristics代表spliterator 本身特征的编码,使用 spliterator  的客户可以这些特性来更好地控制和 优化它的使用

 

实现自己的Spliterator 

这是一个计算单词数量的方法

public class WordCounter {
    private final int counter;
    private final boolean lastSpace;

    public WordCounter(int counter, boolean lastSpace) {
        this.counter = counter;
        this.lastSpace = lastSpace;
    }

    public WordCounter accumulate(Character c){
        if(Character.isWhitespace(c)){
            return lastSpace? this: new WordCounter(counter,true);
        }else {
            return lastSpace? new WordCounter(counter +1,false):this ;
        }
    }

    public WordCounter combine(WordCounter WordCounter){
        return  new WordCounter(WordCounter.counter +counter, WordCounter.lastSpace);
    }


    public int getCounter() {         return counter;     }

private int countWords(Stream<Character> stream) {
    WordCounter wordCounter  = stream.reduce(new WordCounter(0,true),WordCounter::accumulate  , WordCounter::combine);
    return wordCounter.getCounter();
}

public static void main(String[] args) {
    final String SENTENCE =             " Nel   mezzo del cammin  di nostra  vita " +             "mi  ritrovai in una  selva oscura" +             " ché la  dritta via era   smarrita ";
 Stream<Character > stream = IntStream.range(0,SENTENCE.length()-1).mapToObj(SENTENCE ::charAt);
}
}

 

输出结果: Found 19 words 

 

 

 

 

这里的 accumulate方法定义了如何更改WordCounter的状,或更确切地说是用 哪个状态来建立新的WordCounter

2. 让WordCounter并行工作 

你可以尝试用并行流来加快字数统计,如下所示: 
System.out.println("Found " + countWords(stream.parallel()) + " words");

不幸的是,这次的输出是: 
Found 25 words 

因为原始的String在任意 位置拆分,所以有时一个词会被分为两个词,然后数了两次。如何解决这个问题呢?解决方案就是要确保String不是在随机位置拆开的,而只能在词尾 拆开。要做到这一点,你必须为Character实现一个Spliterator,它只能在两个词之间拆开 String然后由此创建并行流

class WordCounterSpliterator implements Spliterator<Character> {
    private final String string;
    private int currentChar = 0;

    public WordCounterSpliterator(String string) {
        this.string = string;
    }

    @Override
        public boolean tryAdvance(Consumer<? super Character> action) {
        System.out.println("currentChar " + currentChar);
            action.accept(string.charAt(currentChar++));
        return currentChar < string.length();
    }

    @Override
    public Spliterator<Character> trySplit() {
       int currentSize = string.length()-currentChar;
       if (currentSize<10) return null;
       for (int splitPos= currentSize/2+ currentChar;splitPos< string.length();splitPos++){
           System.out.println("currentChar``` " + currentChar);
           if (Character.isWhitespace(string.charAt(splitPos))){
               Spliterator<Character> spliterator
                       = new WordCounterSpliterator(string.substring(currentChar, splitPos));
               currentChar = splitPos;
               return spliterator;
           }
       }
        return null;
    }

    @Override
    public long estimateSize() {
        return string .length()-currentChar;
    }

    @Override
    public int characteristics() {
        return ORDERED + SIZED + SUBSIZED + NONNULL + IMMUTABLE;
    }
 public static void main(String[] args) {
       final String SENTENCE = " Nel   mezzo del cammin  di nostra  vita " +             "mi  ritrovai in una  selva oscura" +             " ché la  dritta via era   smarrita ";
      /*Stream<Character > stream = IntStream.range(0,SENTENCE.length()-1).mapToObj(SENTENCE ::charAt);
        System.out.println("Found " + countWords(stream) + " words");
*/
        Spliterator<Character> spliterator = new WordCounterSpliterator(SENTENCE);
        Stream<Character> stream = StreamSupport.stream(spliterator, true);
        System.out.println("Found " + countWords(stream) + " words");
    }
}

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值