代码之家  ›  专栏  ›  技术社区  ›  Andrei Suvorkov

不使用size()方法的LinkedList拆分器

  •  1
  • Andrei Suvorkov  · 技术社区  · 6 年前

    给定 LinkedList ,我想通过 Spliterator .我无法使用方法 size() .我必须实施 trySplit() 具有以下条件的方法:如果 分离器 至少有5个元素,返回 new Spliterator ,将通过前4个元素;其他的 return null .我不知道如何在以下条件下拆分它。现在我只能得到一批元素。如何获取所有批次?我在这项任务中挣扎了5个多小时,运气不好。提前感谢您!

    https://docs.oracle.com/javase/8/docs/api/java/util/Spliterator.html 提供如何使用的信息 分离器 ,当 大小() 已知/允许。

    接口:

    import java.util.Spliterator;
    import java.util.stream.Stream;
    import java.util.stream.StreamSupport;
    
    public interface Li<A> {
      Spliterator<A> getSpliterator();
    
      default Stream<A> stream() {
        return StreamSupport.stream(getSpliterator(), false);
      }
    
      default Stream<A> parallelStream() {
        return StreamSupport.stream(getSpliterator(), true);
      }
    }
    

    类别:

    import java.util.Spliterator;
    import java.util.function.Consumer;
    
    public class LL<A> implements Li<A>{
      private A hd;
      private LL<A> tl;
    
      public boolean isEmpty(){
        return hd == null && tl == null;
      }
    
      public void add(A a){
        if (isEmpty()){
          tl = new LL<>();
          hd = a;
        }else{
          tl.add(a);
        }
      }
    
      public LL(A hd, LL<A> tl){
        this.hd = hd;
        this.tl = tl;
      }
    
      public LL() {
        this(null, null);
      }
    
      public A get(int i) {
        return i==0 ? hd : tl.get(i-1);
      }
    
      @Override
      public Spliterator<A> getSpliterator(){
        return new MySplitter(0, Integer.MAX_VALUE,this);
      }
    
      private class MySplitter implements Spliterator<A>{
        private LL<A> ll;
        int start;
        int end;
    
        MySplitter(int start, int end, LL<A> ll){
          this.ll = ll;
          this.start = start;
          this.end = end;
        }
    
        public A get(int i){
          return i==0 ? hd : tl.get(i-1);
        }
    
        @Override
        public boolean tryAdvance(Consumer<? super A> action){
          if (this.get(start) != null && start < end) {
            action.accept(ll.get(start++));
            return true;
          }else {
            return false;
          }
        }
    
        @Override
        public Spliterator<A> trySplit(){
          try {
            ll.get(start + 5);
            end = start + 5;
          }catch (Exception e){
            return null;
          }
          start = end;
          end += 5;
          return new MySplitter(start, start + 4, ll).trySplit();
        }
    
        @Override
        public long estimateSize(){
          return Long.MAX_VALUE;
        }
    
        @Override
        public int characteristics(){
          return ORDERED | SUBSIZED;
        }
      }
    }
    

    主要方法:

    public static void main (String[] args){
      LL<String> l = new LL();
      l.add("1");
      l.add("2");
      l.add("3");
      l.add("4");
      l.add("5");
      l.add("6");
      l.add("7");
      l.add("8");
      l.add("9");
      l.add("10");
      l.add("11");
      l.add("12");
      l.add("13");
    
      l.stream().forEach(System.out::println);
      System.out.println();
      System.out.println("now parallel");
      System.out.println();
      l.parallelStream().forEach(System.out::println);
    }
    

    预期输出:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    now parallel
    
    5
    6
    7
    8
    1
    2
    3
    4
    13
    9
    10
    11
    12
    

    实际输出:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    now parallel
    
    6
    7
    8
    9
    10
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   Andrei Suvorkov    6 年前

    我终于解决了这个问题。解决问题的关键在于 trySplit() 方法实现错误。首先我要检查前五个元素 LL 存在。然后我创建了一个新的 LL<>(); 并用给定列表中的前四个元素填充它。然后我改变了头部的参考 hd = tl.tl.tl.tl.hd; 和尾巴 tl = tl.tl.tl.tl.tl; .之后,我将返回 new MySplitter(temp.hd, temp.tl); 对象固定工作 LL公司 等级如下:

    public class LL<A> implements Li<A>{
      private A hd;
      private LL<A> tl;
    
      private boolean isEmpty(){
        return hd == null && tl == null;
      }
    
      public void add(A a){
        if (isEmpty()){
          tl = new LL<>();
          hd = a;
        }else{
          tl.add(a);
        }
      }
    
      private LL(A hd, LL<A> tl){
        this.hd = hd;
        this.tl = tl;
      }
    
      private LL() {
        this(null, null);
      }
    
      @Override
      public Spliterator<A> getSpliterator(){
        return new MySplitter(hd, tl);
      }
    
      public static void main (String[] args) {
        LL<String> l = new LL();
        l.add("1");
        l.add("2");
        l.add("3");
        l.add("4");
        l.add("5");
        l.add("6");
        l.add("7");
        l.add("8");
        l.add("9");
        l.add("10");
        l.add("11");
        l.add("12");
        l.add("13");
    
        l.stream().forEach(System.out::println);
        System.out.println();
        System.out.println("now parallel");
        System.out.println();
        l.parallelStream().forEach(System.out::println);
      }
    
      private class MySplitter implements Spliterator<A> {
        private LL<A> tl;
        private A hd;
    
        MySplitter(A hd, LL<A> tl){
          this.tl = tl;
          this.hd = hd;
        }
    
        @Override
        public boolean tryAdvance(Consumer<? super A> action){
          if (hd != null) {
            action.accept(hd);
            hd = tl.hd;
            tl = tl.tl;
            return true;
          }else {
            return false;
          }
        }
    
        @Override
        public Spliterator<A> trySplit(){
          if(hd != null && tl.hd != null && tl.tl.hd != null && tl.tl.tl.hd != null
              && tl.tl.tl.tl.hd != null && tl.tl.tl.tl.tl.hd != null){
            LL<A> temp = new LL<>();
            temp.add(hd);
            temp.add(tl.hd);
            temp.add(tl.tl.hd);
            temp.add(tl.tl.tl.hd);
            hd = tl.tl.tl.tl.hd;
            tl = tl.tl.tl.tl.tl;
            return new MySplitter(temp.hd, temp.tl);
          }
          return null;
        }
    
        @Override
        public long estimateSize(){
          return Long.MAX_VALUE;
        }
    
        @Override
        public int characteristics(){
          return ORDERED;
        }
      }
    }
    

    输出为:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    now parallel
    
    5
    6
    7
    8
    9
    10
    11
    12
    13
    1
    2
    3
    4