美文网首页
Guava-Splitter

Guava-Splitter

作者: 63f4fe6cfa47 | 来源:发表于2022-03-11 23:56 被阅读0次

    静态工厂模式提供了六个静态方法,从上往下分别是:

    • 基于字符分隔
    • 基于正则表达式分隔
    • 字符串分隔
    • 它自己的字符匹配器分隔
    • 按指定长度划分,必须大于0
    image.png

    最终都会返回splitter对象,Splitter构造方法的参数是一个接口,接口内就一个返回值为字符串迭代器的方法。所以每个静态方法生成splitter对象时都需要实现Strategy接口的方法。

      //Splitter构造方法
      private Splitter(Strategy strategy) {
        this(strategy, false, CharMatcher.none(), Integer.MAX_VALUE);
      }
      //Strategy接口
      private interface Strategy {
        Iterator<String> iterator(Splitter splitter, CharSequence toSplit);
      }
    

    splitter实现的每个Strategy接口方法,返回值都是SplittingIterator,它是个抽象类继承了AbstractIterator,
    而AbstractIterator又继承了Iterator,那此处又得实现SplittingIterator的两个抽象方法,也就是separatorStart和separatorEnd,他们分别指得是:

    • separatorStart:参数start就是当前开始的下标值,返回当前下标之后的第一个指定分隔符所在的下标
    • separatorEnd:返回separatorStart值+1的值
      public static Splitter on(final CharMatcher separatorMatcher) {
        checkNotNull(separatorMatcher);
        //通过构造方法创建一个Splitter对象
        return new Splitter(
            //new Strategy接口,实现接口的iterator方法
            new Strategy() {
              //SplittingIterator类是个抽象类,需要重写抽象方法
              @Override
              public SplittingIterator iterator(Splitter splitter, final CharSequence toSplit) {
                return new SplittingIterator(splitter, toSplit) {
                  @Override
                  int separatorStart(int start) {
                    return separatorMatcher.indexIn(toSplit, start);
                  }
    
                  @Override
                  int separatorEnd(int separatorPosition) {
                    return separatorPosition + 1;
                  }
                };
              }
            });
      }
    

    最后计算的核心代码:

    @CheckForNull
        @Override
        protected String computeNext() {
          //offset是开始寻找的下标
          int nextStart = offset;
          while (offset != -1) {
            int start = nextStart;
            int end;
            //返回指定分隔符所在的下标
            int separatorPosition = separatorStart(offset);
            if (separatorPosition == -1) {
              //没找到分隔符,返回-1
              end = toSplit.length();
              offset = -1;
            } else {
              //找到分隔符,给offset赋值分隔符下标位置+1,下次就从offset的位置开始寻找
              end = separatorPosition;
              offset = separatorEnd(separatorPosition);
            }
            //第一个字符就是分隔符
            if (offset == nextStart) {
              offset++;
              //下次开始的下标值大于需处理的字符长度
              if (offset > toSplit.length()) {
                offset = -1;
              }
              continue;
            }
            //如果调用过splitter.trimResults(CharMatcher trimmer)方法,就会在开头和结尾将匹配的字符也去除
            while (start < end && trimmer.matches(toSplit.charAt(start))) {
              start++;
            }
            while (end > start && trimmer.matches(toSplit.charAt(end - 1))) {
              end--;
            }
            //如果执行过splitter.omitEmptyStrings()方法,就会将结果中的空字符串去除
            if (omitEmptyStrings && start == end) {
              nextStart = offset;
              continue;
            }
            
            //如果执行过splitter.limit(int i)方法,就会在到达指定下标时停止字符串分隔,将剩下的未分割的字符串都放到数组结果的最后一个元素中
            if (limit == 1) {
              end = toSplit.length();
              offset = -1;
              while (end > start && trimmer.matches(toSplit.charAt(end - 1))) {
                end--;
              }
            } else {
              limit--;
            }
            //返回开始-第一个分隔符之前的字符
            return toSplit.subSequence(start, end).toString();
          }
          return endOfData();
        }
      }
    

    后续通过静态方法返回的splitter对象所执行的方法都是在执行该核心代码。只是在每次执行方法时做一个标记,在执行核心代码时根据标记值判断是否执行,具体详见上方核心代码分析的注释

    相关文章

      网友评论

          本文标题:Guava-Splitter

          本文链接:https://www.haomeiwen.com/subject/icyhdrtx.html