2017-05-08 9 views
1

"key1:value1|prop:id|key3:value3|id:ABC.CDE|key4:value4"과 같은 문자열이 있는데 어떻게 ID 키까지 Splitter.MapSplitter from Guava을 사용하여 분할 할 수 있습니까?Guava에서 Splitter.MapSplitter를 사용하여 특정 키까지 문자열을 분할하는 방법은 무엇입니까?

  • Splitter.MapSplitter.on('|').withKeyValuePairs(':").split() 수정이 불가능한지도를 반환하므로,이 경우지도를 통해 ID 키까지 걸어보고 새지도에 항목을 넣어야합니다. 효과적인 해결책으로 보이지 않습니다.
  • String.substring(0, String.indexOf('|', String.indexOf("id"))) "id"문자열은 id 키 이전의 모든 값의 하위 문자열 일 수 있기 때문에 옵션이 아닙니다.
  • 또는 두 개의 스플리터 인 entrySplitter를 사용하여 문자열을 항목으로 분할하고 keyValueSplitter를 사용하여 항목을 키 - 값 쌍으로 분할 한 다음 특정 키에 도달하지 않은 상태에서지도에 배치 할 수 있습니다.

가장 좋은 해결책은 무엇입니까?

+0

"id 키까지"란 무엇을 의미합니까? "id"앞에 모든 키 - 값 쌍을 유지하고 나머지는 버리려고한다는 것을 의미합니까? –

+0

예. 가장 효과적인 방법 위에 String에서 다음 매핑을 얻고 싶습니다. key1을 value1로, prop를 id로, key3을 value3으로, id를 ABC.CDE로 가져 오려고합니다. – AggregateException

답변

0

MapSplitter의 출력을 다른 Map으로 복사하고 조작합니다 (키 순서가 유지된다고 가정). 부분적으로 파싱하는 것 외에는 다른 해결책이 없습니다.

당신이 id이 첫 번째 키의 경우 |id:...| 또는 id:...|처럼, 뭔가 더 구체적인 검색해야하므로 "ID"아마도 다른 곳에서 나타나는에 대한 당신의 발언은 올바른 것입니다. 모든

private static final Pattern ID_REGEX = Pattern.compile("(^|\\|)id:.+?\\|"); 
... 
Matcher matcher = ID_REGEX.matcher(line); 
if (matcher.find()) { 
    lineForMapSplitter = line.substring(0, matcher.end()-1); 
} 
0

첫째, 오히려 Splitter#withKeyValueSeparator (여기에 직접 Splitter.MapSplitter 사용하지만,하지 않습니다 Splitter.on('|').withKeyValueSeparator(':')을 둘째, 귀하의 경우에 가장 효율적인 방법은 수동으로 분할 쌍과 술어 경우 (키에 대한 다음 분할 쌍 될 것입니다. == id)가 충족되지 않고 맨 끝까지지도를 만들지 않습니다.

TIMTOWDI,하지만 사용 사례에 유용한 방법이있는 jOOL을 사용하고 있습니다. Seq.seq(Iterable)은 스트림을 만드는 간단한 도우미이며, 더 중요한 것은 Seq#limitUntilClosed(Predicate)id 키가 발견 될 때까지 모든 값을 선택합니다 :

private static final Splitter PAIRS_SPLITTER = Splitter.on('|'); 
private static final Splitter KEY_VALUE_SPLITTER = Splitter.on(':'); 
private static final String INVALID_ENTRY_MESSAGE = "Chunk [%s] is not a valid entry"; 

private Map<String, String> homebrewMapSplitter(final String string) 
{ 
    return Seq.seq(PAIRS_SPLITTER.split(string)) 
      .map(this::createEntry) 
      .limitUntilClosed(e -> e.getKey().equals("id")) 
      .collect(ImmutableMap.toImmutableMap(
        Map.Entry::getKey, 
        Map.Entry::getValue) 
      ); 
} 

// ~copied from MapSplitter#split(CharSequence) 
private Map.Entry<String, String> createEntry(final String entry) 
{ 
    Iterator<String> entryFields = KEY_VALUE_SPLITTER.split(entry).iterator(); 
    checkArgument(entryFields.hasNext(), INVALID_ENTRY_MESSAGE, entry); 
    String key = entryFields.next(); 

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

    checkArgument(!entryFields.hasNext(), INVALID_ENTRY_MESSAGE, entry); 

    return Maps.immutableEntry(key, value); 
}