在Java中将string拆分为长度相等的子string

如何将string"Thequickbrownfoxjumps"拆分为Java中的大小相同的子string。 例如。 4个相同大小的"Thequickbrownfoxjumps"应该给出输出。

 ["Theq","uick","brow","nfox","jump","s"] 

类似的问题:

将string拆分为Scala中的等长子string

这是正则expression式的单行版本:

 System.out.println(Arrays.toString( "Thequickbrownfoxjumps".split("(?<=\\G.{4})") )); 

\G是一个零宽度断言,匹配前一场比赛结束的位置。 如果之前没有匹配,则匹配input的开头,与\A相同。 封闭倒序与最后一场比赛结束时的四个字符相匹配。

向后看和\G是高级正则expression式function,不支持所有的口味。 此外, \G并没有贯彻支持它的口味。 这个技巧可以在Java ,Perl,.NET和JGSoft中使用,但不能在PHP (PCRE),Ruby 1.9或者TextMate(都是Oniguruma)中使用。 JavaScript的/y (粘性标记)不像\G那么灵活,即使JS支持向后看也不能这样使用。

我应该提到,如果您有其他select,我不一定会推荐这个解决scheme。 其他答案中的非正则expression式解决scheme可能更长,但它们也是自我logging的; 这只是与此相反 。 ;)

另外,这在Android中不起作用,它不支持在向后看中使用\G

那么,用暴力来做这件事相当容易:

 public static List<String> splitEqually(String text, int size) { // Give the list the right capacity to start with. You could use an array // instead if you wanted. List<String> ret = new ArrayList<String>((text.length() + size - 1) / size); for (int start = 0; start < text.length(); start += size) { ret.add(text.substring(start, Math.min(text.length(), start + size))); } return ret; } 

我不认为这是真的值得使用正则expression式。

编辑:我的推理不使用正则expression式:

  • 这不使用正则expression式的任何真正的模式匹配。 这只是计数。
  • 怀疑上述会更有效率,虽然在大多数情况下,这并不重要
  • 如果你需要在不同的地方使用不同的大小,你可以得到重复或者帮助函数来根据参数-ick生成正则expression式本身。
  • 在另一个答案提供的正则expression式首先没有编译(无效转义),然后没有工作。 我的代码第一次工作。 这更多地certificate了正则expression式与普通代码,IMO的可用性。

Google Guava的这个function非常简单:

 for(final String token : Splitter .fixedLength(4) .split("Thequickbrownfoxjumps")){ System.out.println(token); } 

输出:

 Theq uick brow nfox jump s 

或者,如果你需要结果作为一个数组,你可以使用这个代码:

 String[] tokens = Iterables.toArray( Splitter .fixedLength(4) .split("Thequickbrownfoxjumps"), String.class ); 

参考:

  • Splitter.fixedLength()
  • Splitter.split()
  • Iterables.toArray()

注意:Splitter结构显示在上面,但由于Splitters是不可变的,可重用的,所以将它们存储在常量中是一个很好的习惯:

 private static final Splitter FOUR_LETTERS = Splitter.fixedLength(4); // more code for(final String token : FOUR_LETTERS.split("Thequickbrownfoxjumps")){ System.out.println(token); } 

如果你使用Google的番石榴通用库(老实说,任何新的Java项目可能都应该是这样),这对于Splitter类来说是非常微不足道的:

 for (String substring : Splitter.fixedLength(4).split(inputString)) { doSomethingWith(substring); } 

就是这样 。 简单!

 public static String[] split(String src, int len) { String[] result = new String[(int)Math.ceil((double)src.length()/(double)len)]; for (int i=0; i<result.length; i++) result[i] = src.substring(i*len, Math.min(src.length(), (i+1)*len)); return result; } 
 public String[] splitInParts(String s, int partLength) { int len = s.length(); // Number of parts int nparts = (len + partLength - 1) / partLength; String parts[] = new String[nparts]; // Break into parts int offset= 0; int i = 0; while (i < nparts) { parts[i] = s.substring(offset, Math.min(offset + partLength, len)); offset += partLength; i++; } return parts; } 

你可以使用来自String.class (处理exception)的substring或来自Apache lang commons (它为你处理exception)

 static String substring(String str, int start, int end) 

把它放在一个循环内,你很好走。

我宁愿这个简单的解决scheme:

 String content = "Thequickbrownfoxjumps"; while(content.length() > 4) { System.out.println(content.substring(0, 4)); content = content.substring(4); } System.out.println(content); 

如果你想分割string,例如从右向左分割1010001111[10, 1000, 1111] ,这里是代码:

 /** * @param s the string to be split * @param subLen length of the equal-length substrings. * @param backwards true if the splitting is from right to left, false otherwise * @return an array of equal-length substrings * @throws ArithmeticException: / by zero when subLen == 0 */ public static String[] split(String s, int subLen, boolean backwards) { assert s != null; int groups = s.length() % subLen == 0 ? s.length() / subLen : s.length() / subLen + 1; String[] strs = new String[groups]; if (backwards) { for (int i = 0; i < groups; i++) { int beginIndex = s.length() - subLen * (i + 1); int endIndex = beginIndex + subLen; if (beginIndex < 0) beginIndex = 0; strs[groups - i - 1] = s.substring(beginIndex, endIndex); } } else { for (int i = 0; i < groups; i++) { int beginIndex = subLen * i; int endIndex = beginIndex + subLen; if (endIndex > s.length()) endIndex = s.length(); strs[i] = s.substring(beginIndex, endIndex); } } return strs; } 

我问@Alan Moore在接受的解决scheme的评论如何处理换行符。 他build议使用DOTALL。

使用他的build议,我创build了一个小样本:

 public void regexDotAllExample() throws UnsupportedEncodingException { final String input = "The\nquick\nbrown\r\nfox\rjumps"; final String regex = "(?<=\\G.{4})"; Pattern splitByLengthPattern; String[] split; splitByLengthPattern = Pattern.compile(regex); split = splitByLengthPattern.split(input); System.out.println("---- Without DOTALL ----"); for (int i = 0; i < split.length; i++) { byte[] s = split[i].getBytes("utf-8"); System.out.println("[Idx: "+i+", length: "+s.length+"] - " + s); } /* Output is a single entry longer than the desired split size: ---- Without DOTALL ---- [Idx: 0, length: 26] - [B@17cdc4a5 */ //DOTALL suggested in Alan Moores comment on SO: https://stackoverflow.com/a/3761521/1237974 splitByLengthPattern = Pattern.compile(regex, Pattern.DOTALL); split = splitByLengthPattern.split(input); System.out.println("---- With DOTALL ----"); for (int i = 0; i < split.length; i++) { byte[] s = split[i].getBytes("utf-8"); System.out.println("[Idx: "+i+", length: "+s.length+"] - " + s); } /* Output is as desired 7 entries with each entry having a max length of 4: ---- With DOTALL ---- [Idx: 0, length: 4] - [B@77b22abc [Idx: 1, length: 4] - [B@5213da08 [Idx: 2, length: 4] - [B@154f6d51 [Idx: 3, length: 4] - [B@1191ebc5 [Idx: 4, length: 4] - [B@30ddb86 [Idx: 5, length: 4] - [B@2c73bfb [Idx: 6, length: 2] - [B@6632dd29 */ } 

但是我也喜欢@Jon Skeets解决schemehttps://stackoverflow.com/a/3760193/1237974 。 对于大型项目中的可维护性,并不是每个人在正则表​​达式中都有相同的经验,我可能会使用Jons解决scheme

另一个蛮力解决scheme可能是,

  String input = "thequickbrownfoxjumps"; int n = input.length()/4; String[] num = new String[n]; for(int i = 0, x=0, y=4; i<n; i++){ num[i] = input.substring(x,y); x += 4; y += 4; System.out.println(num[i]); } 

代码只是用子string遍历string

  import static java.lang.System.exit; import java.util.Scanner; import Java.util.Arrays.*; public class string123 { public static void main(String[] args) { Scanner sc=new Scanner(System.in); System.out.println("Enter String"); String r=sc.nextLine(); String[] s=new String[10]; int len=r.length(); System.out.println("Enter length Of Sub-string"); int l=sc.nextInt(); int last; int f=0; for(int i=0;;i++){ last=(f+l); if((last)>=len) last=len; s[i]=r.substring(f,last); // System.out.println(s[i]); if (last==len)break; f=(f+l); } System.out.print(Arrays.tostring(s)); }} 

结果

  Enter String Thequickbrownfoxjumps Enter length Of Sub-string 4 ["Theq","uick","brow","nfox","jump","s"] 
 @Test public void regexSplit() { String source = "Thequickbrownfoxjumps"; // define matcher, any char, min length 1, max length 4 Matcher matcher = Pattern.compile(".{1,4}").matcher(source); List<String> result = new ArrayList<>(); while (matcher.find()) { result.add(source.substring(matcher.start(), matcher.end())); } String[] expected = {"Theq", "uick", "brow", "nfox", "jump", "s"}; assertArrayEquals(result.toArray(), expected); }