Guava Splitter,Splitter与Java split的对比

Splitter

Java提供的字符串分割方法split,split源码分析如下。

public String[] split(String regex, int limit) {
	char ch = 0;
	// 1. 如果regex只有一位且regex不是列出来的这些特殊字符".$|()[{^?*+\\"
	// 2. 如果regex只有两位且第一位为转义字符,第二位字符小于0或者大于9并且小于a或者大于z并且小于A或者大于Z
	// 3. 与编码相关
	if (((regex.value.length == 1 &&
            ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) ||
            (regex.length() == 2 &&
            regex.charAt(0) == '\\' &&
            (((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 &&
            ((ch-'a')|('z'-ch)) < 0 &&
            ((ch-'A')|('Z'-ch)) < 0)) &&
            (ch < Character.MIN_HIGH_SURROGATE ||
            ch > Character.MAX_LOW_SURROGATE)) {
		
		int off = 0;
		int next = 0;
		boolean limited = limit > 0;
		ArrayList<String> list = new ArrayList<>();
		
		while ((next = indexOf(ch, off)) != -1) {
			if (!limited || list.size() < limit - 1) {
				list.add(substring(off, next));
				off = next + 1;
			} else {    // last one
				//assert (list.size() == limit - 1);
				list.add(substring(off, value.length));
				off = value.length;
				break;
			}
		}
		
		// If no match was found, return this
		if (off == 0)
			return new String[]{this};

		// Add remaining segment
		if (!limited || list.size() < limit)
			list.add(substring(off, value.length));

		// Construct result
		int resultSize = list.size();
		if (limit == 0) {
			while (resultSize > 0 && list.get(resultSize - 1).length() == 0) {
				resultSize--;
			}
		}
	
        String[] result = new String[resultSize];
        return list.subList(0, resultSize).toArray(result);
	}
	return Pattern.compile(regex).split(this, limit);
}

Splitter

Java split方法会忽略掉空内容,但是Guava Splitter不会忽略,也可以进行选择性的忽略。

使用

  • 构造方法

同Joinner,构造方法私有,使用静态方法返回Splitter对象。

// 私有构造方法
private Splitter(Strategy strategy) {
    this(strategy, false, CharMatcher.none(), Integer.MAX_VALUE);
}
private Splitter(Strategy strategy, boolean omitEmptyStrings, CharMatcher trimmer, int limit) {
    this.strategy = strategy;
    this.omitEmptyStrings = omitEmptyStrings;
    this.trimmer = trimmer;
    this.limit = limit;
}

// 静态方法
// 使用指定字符进行分割
public static Splitter on(char separator)
// 使用指定类进行分割
public static Splitter on(final CharMatcher separatorMatcher)
// 使用指定字符串进行分割
public static Splitter on(final String separator)
// 使用指定正则表达式进行分割
public static Splitter on(Pattern separatorPattern) {
    return on(new JdkPattern(separatorPattern));
}
private static Splitter on(final CommonPattern separatorPattern)

Splitter 的实现中有十分明显的策略模式和模板模式,有各种神乎其技的方法覆盖,还有 Guava 久负盛名的迭代技巧和惰性计算。Spliter具有四个成员属性,具体如下。

// 用于描述分割之后内容前后指定字符的策略,例如trimResults将策略定为分割之后结果前后空格删除
private final CharMatcher trimmer;

// 是否删除空字符串
private final boolean omitEmptyStrings;

// 拆分之后的结果个数
private final int limit;

// 实现的策略模式
private final Strategy strategy;

Splitter的策略模式是一个接口,只有一个iterator方法,传入Splitter对象和待拆分的字符串,返回一个字符串的迭代器。

private interface Strategy {
    Iterator<String> iterator(Splitter splitter, CharSequence toSplit);
}
  • 分割方法

split方法,对sequence进行分割,返回一个字符串的迭代器。

public Iterable<String> split(final CharSequence sequence) {
    checkNotNull(sequence);

    return new Iterable<String>() {
        @Override
        public Iterator<String> iterator() {
            return splittingIterator(sequence);
        }

        @Override
        public String toString() {
            return Joiner.on(", ")
            	.appendTo(new StringBuilder().append('['), this)
            	.append(']')
            	.toString();
        }
    };
}
private Iterator<String> splittingIterator(CharSequence sequence) {
    return strategy.iterator(this, sequence);
}

splitToList方法,对sequence进行分割,返回List。

@Beta
public List<String> splitToList(CharSequence sequence) {
    checkNotNull(sequence);

    Iterator<String> iterator = splittingIterator(sequence);
    List<String> result = new ArrayList<String>();

	// 这里采用惰性求值的技巧,在最后调用splitToList时才将结果添加到result中
    while (iterator.hasNext()) {
        result.add(iterator.next());
    }

    return Collections.unmodifiableList(result);
}
  • 其他方法

omitEmptyStrings方法会去除结果中的空字符串。

public Splitter omitEmptyStrings() {
    return new Splitter(strategy, true, trimmer, limit);
}

trimResults方法会去除元素中的左右空字符串,内容中间的空字符串不会去除。

public Splitter trimResults() {
    return trimResults(CharMatcher.whitespace());
}
public Splitter trimResults(CharMatcher trimmer) {
    checkNotNull(trimmer);
    return new Splitter(strategy, omitEmptyStrings, trimmer, limit);
}

fixedLength方法,按子字符串字符数量进行分割。

public static Splitter fixedLength(final int length) {
    checkArgument(length > 0, "The length may not be less than 1");

    return new Splitter(
        new Strategy() {
          	@Override
          	public SplittingIterator iterator(final Splitter splitter, CharSequence toSplit) {
            	return new SplittingIterator(splitter, toSplit) {
              		@Override
              		public int separatorStart(int start) {
                		int nextChunkStart = start + length;
                		return (nextChunkStart < toSplit.length() ? nextChunkStart : -1);
            		}

              		@Override
              		public int separatorEnd(int separatorPosition) {
                		return separatorPosition;
              		}
            	};
          	}
	});
}

limit方法,最多分割limit个子字符串。

public Splitter limit(int limit) {
    checkArgument(limit > 0, "must be greater than zero: %s", limit);
    return new Splitter(strategy, omitEmptyStrings, trimmer, limit);
}

onPattern方法,按正则表达式进行分割。

@GwtIncompatible // java.util.regex
public static Splitter onPattern(String separatorPattern) {
	// 返回按正则表达式进行分割的Splitter
    return on(Platform.compilePattern(separatorPattern));
}

withKeyValueSeparator方法,按照指定的分隔符将字符串分割为map。

public MapSplitter withKeyValueSeparator(String separator) {
    return withKeyValueSeparator(on(separator));
}
  
@Beta
public MapSplitter withKeyValueSeparator(Splitter keyValueSplitter) {
    return new MapSplitter(this, keyValueSplitter);
}

// MapSplitter是Sppiter中的一个内部类,内部覆写了split方法
@Beta
public static final class MapSplitter {
    private static final String INVALID_ENTRY_MESSAGE = "Chunk [%s] is not a valid entry";
    private final Splitter outerSplitter;
    private final Splitter entrySplitter;

    private MapSplitter(Splitter outerSplitter, Splitter entrySplitter) {
      	this.outerSplitter = outerSplitter; // only "this" is passed
      	this.entrySplitter = checkNotNull(entrySplitter);
    }

    public Map<String, String> split(CharSequence sequence) {
      	Map<String, String> map = new LinkedHashMap<String, String>();
      	for (String entry : outerSplitter.split(sequence)) {
        	Iterator<String> entryFields = 							     
        			entrySplitter.splittingIterator(entry);

        	checkArgument(entryFields.hasNext(), INVALID_ENTRY_MESSAGE, entry);
        	String key = entryFields.next();
        	checkArgument(!map.containsKey(key), "Duplicate key [%s] found.", key);

            checkArgument(entryFields.hasNext(), INVALID_ENTRY_MESSAGE, entry);
            String value = entryFields.next();
            map.put(key, value);

            checkArgument(!entryFields.hasNext(), INVALID_ENTRY_MESSAGE, entry);
        }
      	return Collections.unmodifiableMap(map);
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_40739833/article/details/92978142