일반적으로 컬렉션을 반환 할 때마다 스트림을 반환하는 것이 제정신입니까?


19

레거시 코드와 관련이없는 API를 개발하는 동안 종종 결과를 수집하여 Streams 파이프 라인으로 끝나는 메소드를 작성하는 경우가 종종 있습니다. 이 같은:

ImmutableSet<T> deriveSomethingMeaningfulFromPrivateState() {
    return myPrivateThingies.stream()
        .map(this::ownerOfThing)
        .map(Owner::socialStatus)
        .filter(SocialStatus::isHeAFineMatey)
        .collect(MyCustomCollectors.toImmutableSet());
}

이제이 클래스의 대부분의 클라이언트는 일반적으로 요소를 검색하고 반복하기 위해 Collection (이 경우 ImmutableSet)이 필요하지만 일부 클라이언트는 Stream을 사용하여 더 많은 작업을 파이프 할 수 있습니다. 컬렉션에서 새로운 스트림을 얻을 필요가없는 스트림. 따라서 스트림을 반환하면 cliens에 방금 컬렉션이 있으면 얻을 수있는 옵션의 수퍼 세트가 제공됩니다 (결국 항상 collect()스트림 자체를 사용할 수 있음) .

Stream<T> deriveSomethingMeaningfulFromPrivateState() {
    return myPrivateThingies.stream()
        .map(this::ownerOfthing)
        .map(Owner::socialStatus)
        .filter(SocialStatus::isHeAFineMatey);
        // No collect
}

이 접근법은 잠재적 인 결함이 보이지 않기 때문에 시험 해보고 싶어합니다. 그러나 어떤 라이브러리 에서도이 접근법을 보지 못했을 것입니다 (Java 8이 등장한 후 릴리스 된 라이브러리가 많지 않은 것 같습니다). 기존 라이브러리 클래스는 일반적으로 개인 상태에서 무언가를 파생시킬 때 컬렉션을 반환합니다.

Java-8 이전의 자아가 컬렉션을 반환 할 때마다 스트림을 반환하기로 결정하면 나쁜 일 이 있습니까? 아니면 아마도 개인 국가에서 파생 된 모든 반 패턴으로 무언가를하고 있습니까?

답변:


14

myPrivateThingies변경 가능한 경우 비공개 상태와 스트림 결과간에 숨겨진 종속성을 만들었습니다. 클라이언트가 간접적으로 myPrivateThingies상태 변경을 유발할 수 있다면 , collect원래 의도했던 것과 다른 결과를 얻을 수 있습니다 .

myPrivateThingies불변 인 경우 결과는 투명하게 나타납니다. 그러나 시맨틱 가비지 (semantic garbage) , 즉 더 이상 필요하지 않은 많은 양의 메모리를 유지하는 데주의 해야 할 또 하나의 문제가 있습니다 . 한다고 가정은 myPrivateThingies매우 크고 스트림을 수집하는 결과가 작다. 클라이언트는 스트림을 생성 한 객체에 대한 모든 참조를 버린 후 오랫동안 스트림을 유지할 수 있지만 가비지 수집 stream은 계속 유지 myPrivateThingies됩니다. 결과를 열심히 수집하면 풀 수 myPrivateThingies있습니다.

이것은 실제로 호출 할 때 Java 7 이전에 발생했습니다 substring. 오라클은 매번 서브 스트링을 복사하지 않음으로써 잠재적 인 효율성 절감이 과도한 메모리 소비를 가진 일반 사용자를 놀라게 할 가치가 없다고 결정했습니다. 그것은 이전의 행동 (예 : 파서)에 대한 실제 사용 사례는 없었지만 종종 결과를 열심히 수집하는 것이 충분히 빠르다는 것을 말하는 것은 아니며, 그러한 일이 발생하면 프로와 잠재적 인 단점이 없습니다.

반면에 스트림을 반환하면 클라이언트가 원하는 데이터 구조를 선택하여 결과를 유지하는 데 사용할 데이터 구조를 선택할 수 있습니다. 두 가지 옵션을 모두 제공하는 것이 좋습니다.


4

고려해야 할 가장 중요한 사항은 다음과 같습니다. Streams는 한 번만 반복 할 수 있지만, 유연성이 더 뛰어납니다 . 결과에 대해 추가 반복 처리를 수행 Collection하기 위해 더 많은 Streams 를 작성 하거나 s 를 작성할 수도 있습니다 Iterator.

따라서 메소드 호출자가 결과를 한 번만 사용할지 확실하지 않으면를 반환하는 것이 좋습니다 Collection.


샘플 코드에는 한 가지 명백한 오류가 있습니다. 왜 SocialStatus사람이라는 개념이 he있습니까?


3

내 견해로는 그렇지 않다. 스트림으로 수행 할 수있는 작업은 컬렉션으로 수행 할 수있는 작업의 엄격한 상위 집합이며 종종 더 효율적으로 만들 수 있으므로 익숙하지 않은 경우를 제외하고 사용하지 않을 이유가 없습니다. "Lambda 표현은 Java 8의 관문 약물이지만 Streams는 진정한 중독입니다." (Venkat Subramaniam, Java 기능 프로그래밍 )

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.