2016-08-09 3 views
0

Java 8 Streams를 사용하여 쉼표로 구분 된 문자열 목록을 줄이고 "and"접두사 "and"를 마지막 요소에만 줄 수 있습니까?Java 8 스트림을 사용하여 마지막 요소에만 문자열 추가 접두어 목록 줄이기

예 :

List<String> ls = Arrays.asList("tom","terry","john","kevin","steve"); 

String result = ls.stream().map(String::toString) 
       .collect(Collectors.joining(", ")); 

System.out.println(result); 

이 문 인쇄 => 톰, 테리, 존, 케빈, 스티브. 하지만 나는 톰, 테리, 존, 케빈, 스티브 같은 명단을 인쇄하고 싶었습니다.

+0

당신의 코드. 그것은 훨씬 더 쉽게 읽을 수 있습니다! – sascha10000

답변

2

두 솔루션을. 실제로

서투른 복용 하위 목록은 :

class SbS { 
     StringBuilder sb = new StringBuilder(); 
     String s = ""; 

     @Override 
     public String toString() { 
      return sb + (s.empty() ? "" : " and " + s); 
     } 
    } 
    result = ls.stream() 
      .collect(SbS::new, 
       (a, s) -> { 
        a.sb.append(a.sb.length() == 0 ? "" : ", ").append(a.s); a.s = s; 
       }, 
       (a1, a2) -> {}).toString(); 

이 마음 : 클래스 정의가 내부에 배치해야

String result = ls.stream() 
      .limit(ls.size() - 1) 
      .collect(Collectors.joining(", ")) + " and " + ls.get(ls.size() - 1); 

한 장소를 이동하는 클래스를 사용하여 방법. 그렇지 않으면 static이 필요합니다. (a, s)의 람다는 SbS의 한 방법 일 수 있습니다. 병렬 처리에 대한 지원은 독자에게 (a1, a1)으로 진행됩니다.

1

스트림을 사용하면이 작업을보다 쉽게 ​​수행 할 수 있습니다. 당신은 단지뿐만 아니라 String::replaceAll을 사용할 수 있습니다 :

String input = "tom, terry, john, kevin, steve"; 
String result = input.replaceAll(", (\\w+)$", " and $1"); 

System.out.println(result); 

출력 :

tom, terry, john, kevin and steve 
+0

'map()'이 필요 없다고 생각합니다. 각 문자열에서'toString' ...을 호출합니다. 말하자면,이 경우 스트림이 필요한 것은 아니라고 생각합니다. [String.join (",", ls)] (https://docs.oracle.com/javase /8/docs/api/java/lang/String.html#join-java.lang.CharSequence-java.lang.Iterable-) – vlaz

+0

@Vld 당신 말이 맞습니다. 그러나 나는 OP가 입력이 문자열이 아니라 다른 객체와 같은 경우가 있다고 의심한다. 그리고 이것은 실제 상황에 가장 가까운 예이다. 나는 주로 내 라인에 대한 입력이 어떻게 만들어 졌는지 무시했다. –

+0

나는'ls.toString(). replaceAll ("^. |. $", "") .replaceAll (", (\\ w +) $", "$ 1")' 전체 스트림 열차 잔해 – Bohemian

0

스트림 API는 이것을 달성하기위한 표준 방법을 제공하지 않습니다. 표준 스트림 API를 확장하는 내 StreamEx 라이브러리에는 여기에 도움이되는 mapLast 메서드가 있습니다. 그것이 다른 사람으로 만 마지막 스트림 요소 떠나 모든 매핑 할 수 있습니다 : 다음

System.out.println(StreamEx.of(ls).mapLast("and "::concat).joining(", ")); 

결과 :이 확인되는 전에 쉼표를 추가 "및"고

tom, terry, john, kevin, and steve 

주 (Oxford Comma 참조). (예 : 문장 부호를 금지 다른 언어를 사용하거나 실제로는) 그것을 좋아하지 않는 경우에, 그것은 다소 시간이 오래 방식으로 달성 될 수있다 :

당신은 새로운 라인을 만들고 들여 쓰기가 강조로 4 공백을 사용할 필요가
StreamEx.of(ls) 
     .mapLastOrElse(", "::concat, " and "::concat) 
     .joining().substring(", ".length()); 
+0

옥스포드 쉼표의 문제는 정확하게 두 요소가있을 때 나타나지 않아야한다는 것입니다. – Holger

+0

@Holger, 그건 분명히 문제입니다.이 모든 사례를 해결하는 특수 수집기를 내 라이브러리에 추가하는 것은 다른 언어가 구두점 규칙이 다를 수 있으므로 너무 구체적입니다. 아마도 ICU4J와 같은 프로젝트는 자바 8 지향형이라면 그러한 콜렉터를 제공 할 수 있습니다 ... –

+1

특정 인간 언어로 데이터 구조를 포맷팅하는 것은 아웃 오브 바운드 솔루션이어야하는 작업이 아닙니다. 스트림 기반). UI의 경우에는 최신 상태의 템플리트 문자열이있는 리소스 번들이 있습니다. – Holger

관련 문제