2017-09-21 5 views
0

私は特定の形式で来ている文字列を持っているので、その文字列をマップに解析したい。私は、文字列をMapに解析する以下のメソッドを持っており、正常に動作します。文字列のフォーマットされた文字列を同じキーを何度も持つマップに解析しますか?

public static Map<String, String> parseStringToMap(String payload) { 
    try { 
     return Maps.newHashMap(Splitter.on("|").withKeyValueSeparator("=").split(payload)); 
    } catch (Exception ex) { 
     return ImmutableMap.of(); 
    } 
    } 

サンプル例:

"type=3|Id=23456|user=13456" 

は今、時々私は、同じ文字列​​に同じ値で二回同じキーを持って、その後、私の上記の方法が失敗し、それが例外をスローします。たとえば、以下の文字列の場合、それは機能しませんし、失敗し、 typeキーが2回あるため空のマップを返します。

"type=3|Id=23456|user=13456|type=3" 

文字列のペイロードを修正する代わりに、これを修正するにはどうすればよいですか?だから、同じキーが何度も来たら、失敗してしまうのではなく、そのキー値をマップに上書きするとしましょう。そして私はMutableマップを戻したいと思います。

私はまだJava 7で作業していますが、これを行うにはどのような方法が最適ですか?

+0

あなたは、Java 8を使用することができますか?その場合は、グループ化コレクタを使用して、 'Map '、またはそれに類するものを構築することができます。 –

+0

@AndyTurner残念ながら、まだJava 7を使用しており、まだJava 8を使用することはできません。 – user1950349

答えて

1

私はグアバでそれを行う方法を知りませんが、それは昔ながらのJavaで行うにはあまりにも難しいことではありません:あなたは、文字列が右側にあることだけ確認したい場合は

Map<String, String> map = new HashMap<>(); 
for (String part : payload.split("\\|")) { 
    String[] subparts = part.split("=", 2); 
    map.put(subparts[0], subparts[1]); 
} 
return map; 

フォーマット(すなわち、パイプで区切られた要素、=記号を含む各がある)、その後、あなただけのこれらを見つけるためにindexOfを使用することができます。

int start = 0; 
while (start < payload.length()) { 
    int end = payload.indexOf('|', start); 
    if (end == -1) { 
    end = payload.length(); 
    } 

    int equalsPos = payload.indexOf('=', start); 
    if (equalsPos > end || equalsPos < 0) { 
    // No = found between adjacent |s. Not valid format. 
    return Collections.emptyMap(); 
    } 

    // Extract the substrings between | and =, and = and the next |. 
    map.put(payload.substring(start, equalsPos), payload.substring(equalsPos + 1, end)); 

    start = end + 1; 
} 
+0

このようにすれば、どのようにそれらのフォーマットになっているかどうかを確認できますか?それらの形式でない場合は、空のマップを返しますか?または、私はちょうどこれをtry catchでラップする必要があります、そして、それがそのフォーマットとその返りの空のマップを基にしていないなら、それは独自に例外をスローしますか? – user1950349

+0

「その形式ではない」とはどういう意味ですか? '='、次に '|'、そして '='など、その間に文字があることは?確かに、indexofを使って文字列内の文字列を検索するだけです。 –

+0

はい、この形式でなければならず、そうでない場合は空のマップを返します。 – user1950349

0

ドキュメントは、重複キーがある場合、分割が例外をスローすることを言う:

@CheckReturnValueパブリックマップ分割(たCharSequence 配列)サブストリングに

スプリット配列は、エントリに各部分を分割 とエントリのそれぞれと変更不可能なマップを返します。たとえば、 Splitter.on( ';')。trimResults()。withKeyValueSeparator( "=>") .split( "a => b; c => b")は、aからaへのマッピングを返します。 「b」および「c」を に変更します。

返されるマップは、シーケンスからのエントリの順序を保持します。

例外: 、IllegalArgumentExceptionを - 指定されたシーケンスが有効なマップエントリに分割されていない、または重複するキー

だからがある場合、あなたは申し訳ありませんが、MapSplitterからスプリットを使用することができない場合! Javaの8で

return Splitter 
     .on("|") 
     .splitToList(payload) 
     .stream() 
     .map(kv -> kv.split("=")) 
     .collect(Collectors.toMap(kv -> kv[0], kv -> kv[1], (d1, d2) -> d1)); 
+0

スプリッターから離れてこれを行うためのより良い方法はありますか? – user1950349

+0

@ user1950349おそらく正規表現を使って入力を修正できますか? –

+0

残念ながら私はまだJava 7です。 – user1950349

関連する問題