Guava-Splitter

2022-03-11  本文已影响0人  63f4fe6cfa47

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

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,他们分别指得是:

  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对象所执行的方法都是在执行该核心代码。只是在每次执行方法时做一个标记,在执行核心代码时根据标记值判断是否执行,具体详见上方核心代码分析的注释

上一篇下一篇

猜你喜欢

热点阅读