如何在不检查大小或超出范围的情况下获取字符串的前n个字符?


162

如何n在不首先进行大小检查(可以接受内联)或冒冒号的情况下,在Java中获取字符串的第一个字符IndexOutOfBoundsException


1
除非您捕获到异常,否则我不知道您打算如何处理字符长度大于String长度的情况。
马特·博姆

2
为什么?您对检查长度或捕获异常有何厌恶?
paxdiablo

1
出于好奇,您为什么要避免尺寸检查。这不是C.
汤姆Hawtin - tackline

我要表达的意思是希望避免if / else块,而不是避免实际检查长度。
antony.trupe

Answers:


346

这是一个整洁的解决方案:

String upToNCharacters = s.substring(0, Math.min(s.length(), n));

意见:尽管此解决方案“精巧”,但我认为它实际上比使用/ 以明显方式使用/ 的解决方案可读性差。如果读者没有看到此技巧,则他/她必须更加努力地理解代码。IMO,代码的含义在/ 版本中更加明显。有关更清洁/更易读的解决方案,请参见@paxdiablo的答案。ifelseifelse


1
+1。如果将其包装在名为safe_substring或substring_safe的函数中(如paxdiablo的答案),则更好,这样用法更易于阅读/意图更加明显。
制造商史蒂夫(Steve)2014年

我不同意你在说什么。如果将其包装在函数中,函数内部的内容无关紧要,并且由于缺乏清晰性,绝对无法解决任何“整洁”的问题。该解决方案的一点是,它是在您的情况“整齐” 希望创建一个包装函数。
斯蒂芬·C

88

不要重新发明轮子...:

org.apache.commons.lang.StringUtils.substring(String s, int start, int len)

Javadoc说:

StringUtils.substring(null, *, *)    = null
StringUtils.substring("", * ,  *)    = "";
StringUtils.substring("abc", 0, 2)   = "ab"
StringUtils.substring("abc", 2, 0)   = ""
StringUtils.substring("abc", 2, 4)   = "c"
StringUtils.substring("abc", 4, 6)   = ""
StringUtils.substring("abc", 2, 2)   = ""
StringUtils.substring("abc", -2, -1) = "b"
StringUtils.substring("abc", -4, 2)  = "ab"

从而:

StringUtils.substring("abc", 0, 4) = "abc"

1
它没有回答问题,但是无论它仍然提供解决方案。如果OP能够理解,我认为这是一个更好的解决方案。
2014年

5
这也可能是指出,有用的StringUtils.substring(yourString, 0, n)是不一样的yourString.substring(0, n)。前者来自StringUtils,而后者正在使用String.substring(如果结束索引超过字符串长度,则会给出异常)。
制造商史蒂夫(Steve)2014年

与FYI一样,如果您查看此方法的源代码,它会通过将末端更改为长度来处理末端大于长度的情况:if (end > str.length()) { end = str.length();}
bholl

1
的最后一个参数StringUtils.substring(String s, int start, int len)不是len,它是end-Index。
gorootde

StringUtils.substring(“ abc”,0,4)=“ abc”,为我工作。谢谢 !
Akash5288 '18

42

Apache Commons LangStringUtils.left为此提供了一种方法。

String upToNCharacters = StringUtils.left(s, n);

这不是最好的解决方案吗?为什么没有那么多人投票呢?
请问

3
也许是因为其他人与您的看法不同?:-)
Stephen C

这个答案比原先提出问题的日期晚得多。
Mulki

@DoWill:因为向您的可执行环境添加(其他)第三方库并不总是值得的。
LarsH

12

关于SO有一类问题有时说得不够完美,这个问题非常危险:-)

也许您可以解释您对使用排除的两种方法之一的厌恶。

如果只是因为您不想在if语句或异常捕获代码中添加代码,一种解决方案是使用一个帮助程序函数来帮您处理它,例如:

static String substring_safe (String s, int start, int len) { ... }

它将事先检查长度并采取相应措施(返回较小的字符串或使用空格填充)。

然后,您完全不必在代码中担心它,只需调用:

String s2 = substring_safe (s, 10, 7);

代替:

String s2 = s.substring (10,7);

如果您似乎担心(基于对其他答案的评论),而在做大量的字符串构建工作时却不破坏代码的流程,这将起作用。


1
您应该更仔细地阅读注释,@ antony,尤其是笑脸,而不要对尝试帮助的人那么珍贵。我只是说您没有给出为什么必须避免使用这两种方法的任何理由。这是使用助手功能的真实答案,这就是为什么它不在注释中。
paxdiablo

1
+1:鉴于OP希望不使代码混乱,这是一种比公认的方法更好的方法。(或参阅包括一个已经具有表现为所期望的功能的库Nickkk的溶液。)
ToolmakerSteve

12
String upToNCharacters = String.format("%."+ n +"s", str);

if n是一个糟糕的变量(因此您必须构造格式字符串),但如果是一个常数,则很清楚:

String upToNCharacters = String.format("%.10s", str);

docs


有趣的替代方法,虽然考虑到四年前给出的更传统的方法,但我无法想象曾经使用过它。
制造商史蒂夫(Steve)2014年

最佳答案,因为输入String只能读取一次,因此无需将其存储在变量中,从而可以将其整齐地嵌入。
profiterole

3

使用substring方法,如下所示:

int n = 8;
String s = "Hello, World!";
System.out.println(s.substring(0,n);

正如一个评论者指出的那样,如果n大于字符串的长度,则将引发异常。一个简单的解决方案是将所有这些都包装if(s.length()<n)else子句中的条件中,您可以选择是只打印/返回整个String还是以其他方式处理它。


1
这有可能导致IndexOutOfBoundsException
antony.trupe 09-10-18

顺便说一句,如果您打算使用Java编程,则应尝试记住String的大多数API方法(java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html)。
马特·博姆

我已经排除了子串,至少不是它本身,不是答案。
antony.trupe

您必须检查大小或捕获异常。请问为什么在您所处的情况下都不做这些事情?
马特·博姆

3
这如何回答这个问题?问题是询问如何不必先进行大小检查,也不必引起需要捕获的异常。
制造商史蒂夫(Steve)2014年

3

如果您有幸与Kotlin一起开发,
可以使用它take来实现您的目标。

val someString = "hello"

someString.take(10) // result is "hello"
someString.take(4) // result is "hell" )))

0

ApacheCommons令我惊讶, StringUtils.abbreviate(String str, int maxWidth)附加“ ...”没有更改后缀的选项。 WordUtils.abbreviate(String str, int lower, int upper, String appendToEnd)查找下一个空白空间。

我将把这个留在这里:

public static String abbreviate(String s, int maxLength, String appendToEnd) {
    String result = s;
    appendToEnd = appendToEnd == null ? "" : appendToEnd;
    if (maxLength >= appendToEnd.length()) {
        if (s.length()>maxLength) {
            result = s.substring(0, Math.min(s.length(), maxLength - appendToEnd.length())) + appendToEnd;
        }
    } else {
        throw new StringIndexOutOfBoundsException("maxLength can not be smaller than appendToEnd parameter length.");
    }
    return result;
}

1
@VolkanGüven因为这句话“ ApacheCommons令我惊讶”。我通过批评神圣的ApacheCommons库犯了罪。或其他...
yuceel

0

Kotlin :(如果有人需要)

var mText = text.substring(0, text.length.coerceAtMost(20))
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.