IT

Java 8 Streams FlatMap 메서드 예제

lottoking 2020. 9. 17. 08:07
반응형

Java 8 Streams FlatMap 메서드 예제


나는 다가오는 Java update, 즉 Java 8 or JDK 8. 예, 참을성이없고 새로운 것이 많이 이해하지 못해요. 간단한 코드가 있습니다.

final Stream<Integer>stream = Stream.of(1,2,3,4,5,6,7,8,9,10);
stream.flatMap();

javadocs는

public <R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper)

이 스트림의 각 요소를 매핑 함수를 각 요소에 적용하여 생성 된 매핑 된 스트림의 내용으로 대체 한 결과로 포함 된 스트림을 반환합니다. 매핑 된 각 스트림은 해당 콘텐츠 가이 스트림에 배치 된 후 닫힘. (매핑 된 스트림이 null이면 대신 빈 스트림이 사용됩니다.) 이것은 중간 작업입니다.

누군가가에 대한 간단한 실제를 flatMap작성하는 것이 좋습니다 이전 Java 버전에서 Java[6,7]코드를 작성하는 방법과 .NET을 사용하여 루틴을 코드화하는 방법 에 대해 감사하겠습니다 Java 8.


질문에 내용과 같이 이미 언어 스트림flatMap 에는 의미가 없습니다 .Stream<Integer>

그러나 당신이 가지고있는 Stream<List<Integer>>존재는 의미 있고 다음과 같이 할 수 있습니다.

Stream<List<Integer>> integerListStream = Stream.of(
    Arrays.asList(1, 2), 
    Arrays.asList(3, 4), 
    Arrays.asList(5)
);

Stream<Integer> integerStream = integerListStream .flatMap(Collection::stream);
integerStream.forEach(System.out::println);

다음과 같이 인쇄됩니다.

1
2
3
4
5

Java 8 이전 버전을 수행 비용을 지불해야합니다.

List<List<Integer>> integerLists = Arrays.asList(
    Arrays.asList(1, 2), 
    Arrays.asList(3, 4), 
    Arrays.asList(5)
)

List<Integer> flattened = new ArrayList<>();

for (List<Integer> integerList : integerLists) {
    flattened.addAll(integerList);
}

for (Integer i : flattened) {
    System.out.println(i);
}

구성 예

1, 2, 2, 3, 3, 3, 4, 4, 4, 4 등의 시퀀스 (즉, 1x1, 2x2, 3x3 등)를 만들고 싶다고 가정 해.

flatMap그것 같이 볼 수 있었다 :

IntStream sequence = IntStream.rangeClosed(1, 4)
                          .flatMap(i -> IntStream.iterate(i, identity()).limit(i));
sequence.forEach(System.out::println);

어디 :

  • IntStream.rangeClosed(1, 4)int1에서 4까지 의 스트림을 만듭니다.
  • IntStream.iterate(i, identity()).limit(i)길이 난 스트림을 생성의 int하므로 적용 i = 4하면 스트림이 생성 됩니다 .4, 4, 4, 4
  • flatMap 스트림을 "평탄화"하고 원래 스트림에 "연결"합니다.

Java <8에서는 두 개의 중첩 루프가 필요합니다.

List<Integer> list = new ArrayList<>();
for (int i = 1; i <= 4; i++) {
    for (int j = 0; j < i; j++) {
        list.add(i);
    }
}

실제 사례

내가 있다고 가정 이제 해 봅시다 List<TimeSeries>각 어디 TimeSeries본질적이다 Map<LocalDate, Double>. 시계열 중 하나 이상에 값이있는 모든 날짜 목록을 가져오고 싶습니다. flatMap구출 :

list.stream().parallel()
    .flatMap(ts -> ts.dates().stream()) // for each TS, stream dates and flatmap
    .distinct()                         // remove duplicates
    .sorted()                           // sort ascending
    .collect(toList());

읽을 수있을뿐만 아니라 갑자기 10 개의 요소를 만 처리 해야하는 경우 추가 만하면 parallel()동시 코드를 작성하지 않고도 성능이 향상됩니다.


구문 목록에서 ASC로 정렬 된 한 단어를 추출합니다.

List<String> phrases = Arrays.asList(
        "sporadic perjury",
        "confounded skimming",
        "incumbent jailer",
        "confounded jailer");

List<String> uniqueWords = phrases
        .stream()
        .flatMap(phrase -> Stream.of(phrase.split(" +")))
        .distinct()
        .sorted()
        .collect(Collectors.toList());
System.out.println("Unique words: " + uniqueWords);

... 그리고 출력 :

Unique words: [confounded, incumbent, jailer, perjury, skimming, sporadic]

풀리지 않는 목록이 지루 생각하는 사람은 나뿐입니까? ;-)

개체를 살펴 보겠습니다. 그런데 실제 세계의 예입니다.

: 반복적 인 작업을 주어진 객체. 중요한 작업 필드 정보 :이 울리기 시작 알림하고 start매번 반복되며 repeatPeriod repeatUnit(예 : 5 시간) repeatCount총 알림 이 있습니다 (시작 시간 포함).

목표 : 각 작업 알림 호출에 대해 하나씩 작업 복사본 목록을 얻습니다.

List<Task> tasks =
            Arrays.asList(
                    new Task(
                            false,//completed sign
                            "My important task",//task name (text)
                            LocalDateTime.now().plus(2, ChronoUnit.DAYS),//first reminder(start)
                            true,//is task repetitive?
                            1,//reminder interval
                            ChronoUnit.DAYS,//interval unit
                            5//total number of reminders
                    )
            );

tasks.stream().flatMap(
        x -> LongStream.iterate(
                x.getStart().toEpochSecond(ZoneOffset.UTC),
                p -> (p + x.getRepeatPeriod()*x.getRepeatUnit().getDuration().getSeconds())
        ).limit(x.getRepeatCount()).boxed()
        .map( y -> new Task(x,LocalDateTime.ofEpochSecond(y,0,ZoneOffset.UTC)))
).forEach(System.out::println);

다수 :

Task{completed=false, text='My important task', start=2014-10-01T21:35:24, repeat=false, repeatCount=0, repeatPeriod=0, repeatUnit=null}
Task{completed=false, text='My important task', start=2014-10-02T21:35:24, repeat=false, repeatCount=0, repeatPeriod=0, repeatUnit=null}
Task{completed=false, text='My important task', start=2014-10-03T21:35:24, repeat=false, repeatCount=0, repeatPeriod=0, repeatUnit=null}
Task{completed=false, text='My important task', start=2014-10-04T21:35:24, repeat=false, repeatCount=0, repeatPeriod=0, repeatUnit=null}
Task{completed=false, text='My important task', start=2014-10-05T21:35:24, repeat=false, repeatCount=0, repeatPeriod=0, repeatUnit=null}

추신 : 누군가가 더 간단한 해결을 제안합니다. 결국 저는 프로가 아닙니다.

업데이트 : @RBz가 자세한 설명을 요청했기 때문에 여기 있습니다. 기본적으로 flatMap은 다른 스트림 내부 스트림의 모든 요소를 ​​출력 스트림에 넣습니다. 여기에 많은 스트림이 있습니다 :). 따라서 초기 스트림 람다 식의 각 Task에 대해 작업 x -> LongStream.iterate...시작 순간을 나타내는 긴 값의 스트림을 만듭니다. 이 스트림은 x.getRepeatCount()인스턴스 로 제한됩니다 . x.getStart().toEpochSecond(ZoneOffset.UTC)값은 에서 시작 하고 각 다음 값은 lambda를 사용하여 계산됩니다 p -> (p + x.getRepeatPeriod()*x.getRepeatUnit().getDuration().getSeconds(). boxed()각 long 값을 가진 스트림을 Long 래퍼 인스턴스로 반환합니다. 그런 다음 해당 스트림의 각 Long은 더 이상 반복되지 않고 정확한 실행 시간을 포함하는 새 Task 인스턴스에 매핑됩니다. 이 샘플에는 입력 목록에 하나의 태스크 만 포함되어 있습니다. 그러나 천이 있다고 상상해보십시오. 그러면 1000 개의 Task 개체 스트림이 생성됩니다. 그리고 뭐flatMap여기서하는 일은 모든 스트림의 모든 태스크를 동일한 출력 스트림에 배치하는 것입니다. 그게 내가 이해하는 전부입니다. 질문 해주셔서 감사합니다!


아주 간단한 예 : 이름과성에 관계없이 전체 이름 목록을 분할하여 이름 목록을 가져옵니다.

 List<String> fullNames = Arrays.asList("Barry Allen", "Bruce Wayne", "Clark Kent");

 fullNames.stream()
            .flatMap(fullName -> Pattern.compile(" ").splitAsStream(fullName))
            .forEach(System.out::println);

다음과 같이 출력됩니다.

Barry
Allen
Bruce
Wayne
Clark
Kent

이것을 감안할 때 :

  public class SalesTerritory
    {
        private String territoryName;
        private Set<String> geographicExtents;

        public SalesTerritory( String territoryName, Set<String> zipCodes )
        {
            this.territoryName = territoryName;
            this.geographicExtents = zipCodes;
        }

        public String getTerritoryName()
        {
            return territoryName;
        }

        public void setTerritoryName( String territoryName )
        {
            this.territoryName = territoryName;
        }

        public Set<String> getGeographicExtents()
        {
            return geographicExtents != null ? Collections.unmodifiableSet( geographicExtents ) : Collections.emptySet();
        }

        public void setGeographicExtents( Set<String> geographicExtents )
        {
            this.geographicExtents = new HashSet<>( geographicExtents );
        }

        @Override
        public int hashCode()
        {
            int hash = 7;
            hash = 53 * hash + Objects.hashCode( this.territoryName );
            return hash;
        }

        @Override
        public boolean equals( Object obj )
        {
            if ( this == obj ) {
                return true;
            }
            if ( obj == null ) {
                return false;
            }
            if ( getClass() != obj.getClass() ) {
                return false;
            }
            final SalesTerritory other = (SalesTerritory) obj;
            if ( !Objects.equals( this.territoryName, other.territoryName ) ) {
                return false;
            }
            return true;
        }

        @Override
        public String toString()
        {
            return "SalesTerritory{" + "territoryName=" + territoryName + ", geographicExtents=" + geographicExtents + '}';
        }

    }

이:

public class SalesTerritories
{
    private static final Set<SalesTerritory> territories
        = new HashSet<>(
            Arrays.asList(
                new SalesTerritory[]{
                    new SalesTerritory( "North-East, USA",
                                        new HashSet<>( Arrays.asList( new String[]{ "Maine", "New Hampshire", "Vermont",
                                                                                    "Rhode Island", "Massachusetts", "Connecticut",
                                                                                    "New York", "New Jersey", "Delaware", "Maryland",
                                                                                    "Eastern Pennsylvania", "District of Columbia" } ) ) ),
                    new SalesTerritory( "Appalachia, USA",
                                        new HashSet<>( Arrays.asList( new String[]{ "West-Virgina", "Kentucky",
                                                                                    "Western Pennsylvania" } ) ) ),
                    new SalesTerritory( "South-East, USA",
                                        new HashSet<>( Arrays.asList( new String[]{ "Virginia", "North Carolina", "South Carolina",
                                                                                    "Georgia", "Florida", "Alabama", "Tennessee",
                                                                                    "Mississippi", "Arkansas", "Louisiana" } ) ) ),
                    new SalesTerritory( "Mid-West, USA",
                                        new HashSet<>( Arrays.asList( new String[]{ "Ohio", "Michigan", "Wisconsin", "Minnesota",
                                                                                    "Iowa", "Missouri", "Illinois", "Indiana" } ) ) ),
                    new SalesTerritory( "Great Plains, USA",
                                        new HashSet<>( Arrays.asList( new String[]{ "Oklahoma", "Kansas", "Nebraska",
                                                                                    "South Dakota", "North Dakota",
                                                                                    "Eastern Montana",
                                                                                    "Wyoming", "Colorada" } ) ) ),
                    new SalesTerritory( "Rocky Mountain, USA",
                                        new HashSet<>( Arrays.asList( new String[]{ "Western Montana", "Idaho", "Utah", "Nevada" } ) ) ),
                    new SalesTerritory( "South-West, USA",
                                        new HashSet<>( Arrays.asList( new String[]{ "Arizona", "New Mexico", "Texas" } ) ) ),
                    new SalesTerritory( "Pacific North-West, USA",
                                        new HashSet<>( Arrays.asList( new String[]{ "Washington", "Oregon", "Alaska" } ) ) ),
                    new SalesTerritory( "Pacific South-West, USA",
                                        new HashSet<>( Arrays.asList( new String[]{ "California", "Hawaii" } ) ) )
                }
            )
        );

    public static Set<SalesTerritory> getAllTerritories()
    {
        return Collections.unmodifiableSet( territories );
    }

    private SalesTerritories()
    {
    }

}

그러면 다음과 같이 할 수 있습니다.

System.out.println();
System.out
    .println( "We can use 'flatMap' in combination with the 'AbstractMap.SimpleEntry' class to flatten a hierarchical data-structure to a set of Key/Value pairs..." );
SalesTerritories.getAllTerritories()
    .stream()
    .flatMap( t -> t.getGeographicExtents()
        .stream()
        .map( ge -> new SimpleEntry<>( t.getTerritoryName(), ge ) )
    )
    .map( e -> String.format( "%-30s : %s",
                              e.getKey(),
                              e.getValue() ) )
    .forEach( System.out::println );

이 메서드는 하나의 함수를 인수로 취하고,이 함수는 하나의 매개 변수 T를 입력 인수로 받아들이고, 매개 변수 R의 한 스트림을 반환 값으로 반환합니다. 이 함수가이 스트림의 각 요소에 적용되면 새 값의 스트림을 생성합니다. 그런 다음 각 요소에 의해 생성 된 이러한 새 스트림의 모든 요소는이 메서드의 반환 값이되는 새 스트림에 복사됩니다.

http://codedestine.com/java-8-stream-flatmap-method/

참고 URL : https://stackoverflow.com/questions/22382453/java-8-streams-flatmap-method-example

반응형