サイズをチェックしたり範囲外に出たりせずに文字列の最初のn文字を取得するにはどうすればよいですか?


163

nJavaで文字列の最初の文字まで取得するには、最初にサイズチェックを行わず(インラインは許容されます)IndexOutOfBoundsException、?


1
例外をキャッチしない限り、文字の長さが文字列の長さより長い場合の処理​​方法を知りません。
Matt Boehm、

2
どうして?長さをチェックしたり、例外をキャッチしたりすることに嫌悪感はありますか?
paxdiablo 2009年

1
好奇心旺盛なのに、なぜサイズチェックを避けたいのか。これはC.ではありません
トムホーティン- tackline

私が表現しようとしたのは、実際に長さをチェックすることへの嫌悪ではなく、if / elseブロックを回避したいという願望でした。
antony.trupe

回答:


347

ここにきちんとした解決策があります:

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

意見:このソリューションは「きちんとしている」が、/ を明白な方法で使用するソリューションよりも実際には読みにくいと思います。読者がこのトリックを見たことがない場合は、コードを理解するのが難しい考える必要があります。IMO、コードの意味は/ バージョンでより明白です。より明確で読みやすいソリューションについては、@ paxdiabloの回答を参照してください。ifelseifelse


1
+1。これがpaxdiabloの回答のようにsafe_substringまたはsubstring_safeという名前の関数にラップされている場合はさらに便利です。これにより、使用法が読みやすくなり、意図がより明確になります。
ToolmakerSteve

私はあなたの言っていることに同意しません。これが関数にラップされている場合は、関数の内部が何であるかは関係ありません。また、明確さの欠如により、「素晴らしさ」よりも明らかに優先されます。この解決策の要点は、ラッパー関数を作成したくない場合には「適切」であるということです
スティーブン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が理解できる場合、これはより良い解決策だと思います。
aullah

5
StringUtils.substring(yourString, 0, n)同じではないことを指摘することも役立つ場合がありますyourString.substring(0, n)。前者はfrom StringUtilsで、後者は使用してString.substringいます(終了インデックスが文字列の長さを超える場合は例外になります)。
ToolmakerSteve

同じようFYIあなたはそのエンドは、長さに終止符を変更することで長さよりも大きい場合を扱うこの方法のためのソースで見れば:if (end > str.length()) { end = str.length();}
bholl

1
の最後のパラメータStringUtils.substring(String s, int start, int len)はlenではなく、end-Indexです。
gorootde 2017

StringUtils.substring( "abc"、0、4)= "abc"、私のために働いた。よろしくお願いします!
Akash5288 2018

42

Apache Commons LangにStringUtils.leftこれを行う方法があります。

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

これは最善の解決策ではありませんか?なぜこれは賛成票が多くないのですか?
行います

3
たぶん他の人があなたと同じ意見を持っていないからでしょうか?:-)
スティーブンC

この回答は、元の質問の質問日よりもはるかに遅れて届きました。
Mulki

@DoWill:(他の)サードパーティのライブラリを実行可能環境に追加することが常に価値があるとは限らないため。
LarsH

12

SOには完全ではない意味のクラスの質問があり、これは非常に危険です:-)

おそらく、除外した2つの方法のいずれかを使用することへの嫌悪感を説明できます。

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、特にスマイリーのコメントをもっと注意深く読んでください。助けようとする人をそれほど尊重しないでください。私は、なぜ2つの方法を回避しなければならなかったのかについて、根拠を与えなかったとだけ述べました。そして、これはヘルパー関数を使用した本物の答えです。そのため、コメントには含まれていません。
paxdiablo 2009年

1
+1:これは、OPがコードを散らかしたくないという要望を踏まえると、受け入れられているアプローチよりもはるかに優れたアプローチです。(または、Nickkkのソリューションに、必要に応じて動作する関数が既に含まれているライブラリを含める方法を参照してください。)
ToolmakerSteve

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

ひどい場合nは変数です(したがって、フォーマット文字列を作成する必要があります)が、定数の場合は非常に明確です。

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

docs


興味深い代替案ですが、4年前に与えられた従来のアプローチを考えると、これを使用することは想像できません。
ToolmakerSteve

入力文字列は1回しか読み取られないため、変数に格納する必要がないため、最良の回答が得られます。これにより、文字列をきれいに埋め込むことができます。
プロフィッテロール

3

次のように、substringメソッドを使用します。

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

nが文字列の長さより大きい場合、1人のコメント投稿者が指摘したように、これは例外をスローします。簡単な解決策の1つは、これらすべてを句の条件if(s.length()<n)にラップelseすることです。文字列全体を出力/返すだけにするか、別の方法で処理するかを選択できます。


1
これはIndexOutOfBoundsExceptionを取得するリスク
antony.trupe

ちなみに、Javaでのプログラミングを計画している場合は、StringのほとんどのAPIメソッド(java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html)を覚えておく必要があります。
Matt Boehm、

私は答えではないので、少なくともそれ自体で部分文字列をすでに除外しました。
antony.trupe 2009年

サイズを確認するか、例外をキャッチする必要があります。これらのいずれかを行ってもあなたの状況でうまくいかないのはなぜですか?
Matt Boehm、

3
これは質問に対する答えですか?問題は、最初にサイズチェックを行わずに、キャッチする必要のある例外を発生させない方法を尋ねることでした。
ToolmakerSteve

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)「...」を追加しました。postfix を変更するオプションはありません。 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 2018年

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.