필터링(distinct(), filter())

public class Example {
  public static void main(String[] args) {
    List<String> names = Arrays.asList("John", "Jack", "Dave", "John");

    names.stream()
      .distinct()
      .forEach(System.out::println);

    names.stream()
      .filter(n -> n.startWith("J"))
      .forEach(System.out::println);

    names.stream()
      .distinct()
      .filter(n -> n.startWith("J"))
      .forEach(System.out::println);
  }
}

매핑(flatMapXXX(), mapXXX(), asXXXStream(), boxed())

flatMapXXX()

flatmap
flatmap
public class Example {
  public static void main(String[] args) {
    List<String> inputs1 = Arrays.asList("java8 lambda", "stream mapping");
    inputs1.stream()
      .flatMap(data -> Arrays.stream(data.split(" ")))
      .forEach(System.out::println);

    List<String> inputs2 = Arrays.asList("10, 20, 30, 40, 50, 60");
    inputs2.stream()
      .flatMapToInt(data -> {
        String[] strArr = data.split(",");
        int[] intArr = new int[strArr.length];

        for(int i = 0; i < strArr.length; ++i) {
          intArr[i] = Integer.parseInt(strArr[i].trim());
        }

        return Arrays.stream(intArr);
      })
      .forEach(System.out::println);
  }
}

mapXXX()

map
map
public class Example {
  public static void main(String[] args) {
    List<Item> items = Arrays.asList(
      new Item("computer", 1000),
      new Item("car", 5000),
      new Item("cell phone", 500)
    );

    items.stream()
      .mapToInt(Item::getCost)
      .forEach(System.out::println);
  }
}

asDoubleStream(), asLongStream(), boxed()

public class Example {
  public static void main(String[] args) {
    int[] arry = {1, 2, 3, 4, 5};

    IntStream intStream = Arrays.stream(intArray);
    intStream
      .asDoubleStream()
      .forEach(System.in::println);

    intStream = Arrays.stream(intArray);
    intStream
      .boxed()
      .forEach(i -> System.out.println(i.intValue()));
  }
}

정렬(sorted())

public class Item implements Comparable<Item> {
  private String name;
  private int cost;
  ...
  @Override
  public int compareTo(Item i) {
    return Integer.compare(cost, i.cost);
  }
}

public class Example {
  public static void main(String[] args) {
    IntStream intStream = Arrays.stream(new int[] {5, 4, 3, 2, 1});
    intStream
      .sorted()
      .forEach(System.out::println);

    List<Item> items = Arrays.asList(
      new Item("computer", 1000),
      new Item("car", 5000),
      new Item("cell phone", 500)
    );

    items.stream()
      .sorted()
      .forEach(i -> System.out.println(i.getCost()));
    
    items.stream()
      .sorted(Comparator.reverseOrder())
      .forEach(i -> System.out.println(i.getCost()));
  }
}

루핑(peek(), forEach())

// Not Work
intStream
  .filter(i -> a % 2 == 0)
  .peek(System.in::println);

// Work
intStream
  .filter(i -> a % 2 == 0)
  .peek(System.in::println)
  .sum();

// Error
intStream
  .filter(i -> a % 2 == 0)
  .forEach(System.in::println)
  .sum();
public class Example {
  public static void main(String[] args) {
    int[] arr = {1, 2, 3, 4, 5};

    Arrays.Stream(arr)
      .filter(i -> i % 2 == 0)
      .peek(System.out::println); // Not Work

    int total = Arrays.Stream(arr)
      .filter(i -> i % 2 == 0)
      .peek(System.out::println)
      .sum();

    Arrays.Stream(arr)
      .filter(i -> i % 2 == 0)
      .forEach(System.out::println);
  }
}

매칭(allMatch(), anyMatch(), noneMatch())

public class Example {
  public static void main(String[] args) {
    int[] arr = {2, 4, 6};

    boolean result = Arrays.stream(arr)
      .allMatch(i -> i % 2 == 0);

    boolean result = Arrays.stream(arr)
      .anyMatch(i -> i % 3 == 0);

    boolean result = Arrays.stream(arr)
      .noneMatch(i -> i % 3 == 0);
  }
}

기본 집계(sum(), count(), average(), max(), min())

public class Example {
  public static void main(String[] args) {
    long count = Arrays.stream(new int[] {1, 2, 3, ,4 ,5})
      .filter(n -> n % 2 == 0)
      .count();

    long sum = Arrays.stream(new int[] {1, 2, 3, ,4 ,5})
      .filter(n -> n % 2 == 0)
      .sum()
      

    double avg = Arrays.stream(new int[] {1, 2, 3, ,4 ,5})
      .filter(n -> n % 2 == 0)
      .average()
      .getAsDouble();

    int max = Arrays.stream(new int[] {1, 2, 3, ,4 ,5})
      .filter(n -> n % 2 == 0)
      .max()
      .getAsInt();

    int min = Arrays.stream(new int[] {1, 2, 3, ,4 ,5})
      .filter(n -> n % 2 == 0)
      .min()
      .getAsInt();

    int first = Arrays.stream(new int[] {1, 2, 3, ,4 ,5})
      .filter(n -> n % 2 == 0)
      .findFirst()
      .getAsInt();
  }
}

Optional

// Error
List<Integer> list = new ArrayList<>();
double avg = list.stream()
  .mapToInt(Integer::intValue)
  .average()
  .getAsDouble();

// Solution 1
Optional optional = list.stream()
  .mapToInt(Integer::intValue)
  .average();

if (optional.isPresent()) {
  System.out.println(optional.getAsDouble());
} else {
  System.out.println(0.0);
}

// Solution 2
double avg = list.stream()
  .mapToInt(Integer::intValue)
  .average()
  .orElse(0.0);
System.out.println(avg);

// Solution 3
list.stream()
  .mapToInt(Integer::intValue)
  .average()
  .ifPresent(System.out::println);

커스텀 집계(reduce())

public class Example {
  public static void main(String[] args) {
    List<Item> items = Arrays.asList(
      new Item("computer", 1000),
      new Item("car", 5000),
      new Item("cell phone", 500)
    );

    int sum1 = items.stream()
      .mapToInt(Item::getCost)
      .sum();

    // reduce(BinaryOperator<Integer> accumulator)
    int sum2 = items.stream()
      .map(Item::getCost)
      .reduce((a, b) -> a + b)
      .get();

    // reduce(int identity, IntBinaryOperator op)
    int sum3 = items.stream()
      .map(Item::getCost)
      .reduce(0, (a, b) -> a + b);
  }
}

수집(Collect)

필터링한 요소 수집

Stream<Member> totalStream = totalList.stream();
Steram<Member> maleStream = totalStream.filter(m -> m.getSex() == Member.Sex.MALE);
Collector<Member, ?, List<Student>> collector = Collectors.toList();
List<Member> maleList = maleStream.collect(collector);

// same
List<Student> maleList = totalList.stream()
  .filter(s -> s.getSex() == Member.Sex.MALE)
  .collect(Collectors.toList());

Stream<Member> totalStream = totalList.stream();
Steram<Member> femaleStream = totalStream.filter(m -> m.getSex() == Member.Sex.FEMALE);
Supplier<HashSet<Member>> supplier = HashSet::new;
Collector<Member, ?, HashSet<Member>> collector = Collectors.toCollection(supplier);
Set<Member> femaleSet = femaleStream.collect(collector);

// same
Set<Member> femaleSet = totalList.stream()
  .filter(s -> s.getSex() == Member.Sex.FEMALE)
  .collect(Collectors.toCollection(HashSet::new));

사용자 정의 컨테이너에 수집

public class MaleMember {
  private List<Member> list;

  public MaleMember() {
    list = new ArrayList<>();
  }

  public void accumulate(Member member) {
    list.add(member);
  }

  public void combine(MaleMember other) {
    list.addAll(other.getList());
  }

  public List<Member> getList() {
    return list;
  }
}

public class Example {
  public static void main(String[] args) {
    List<Member> totalList; // add some elements

    Stream<Member> totalStream = totalList.stream();
    Stream<Member> maleStream = totalStream.filter(m -> m.getSex() == Member.Sex.MALE);
    Supplier<MaleMember> supplier = () -> new MaleMember();
    BiConsumer<MaleMember, Member> accumulator = (mm, m) -> mm.accumulate(m);
    BiConsumer<MaleMember, MaleMember> combiner = (mm1, mm2) -> mm1.combine(mm2);
    MaleMember maleMember = maleStream.collect(supplier, accumulator, combiner);

    // same
    MaleMember maleMember = totalList.stream()
      .filter(m -> m.getSex() == Member.Sex.MALE)
      .collect(
        () -> new MaleMember(),
        (r, t) -> r.accumulate(),
        (r1, r2) -> r1.combine(r2)
      );

    // same
    MaleMember maleMember = totalList.stream()
      .filter(m -> m.getSex() == Member.Sex.MALE)
      .collect(MaleMember::new, MaleMember::accumulate, MaleMember::combine);
  }
}

요소를 그룹핑해서 수집

Stream<Member> totalStream = totalList.stream();
Function<Member, Member.Sex> classifier = Member::getSex;
Collector<Member, ?, Map<Member.Sex, List<Member>>> collector = Collectors.groupingBy(classifier);
Map<Member.Sex, List<Member>> mapBySex = totalStream.collect(collector);

// same
Map<Member.Sex, List<Member>> mapBySex = totalList.stream()
  .collect(Collectors.groupingBy(Member::getSex));

Stream<Member> totalStream = totalList.stream();
Funtion<Member, Member.City> classifier = Member::getCity;
Funtion<Member, String> mapper = Member::getName;
Collector<String, ?, List<String>> collector1 = Collectors.toList();
Collector<Member, ?, List<String>> collector2 = Collectors.mapping(mapper, collector1);
Collector<Member, ?, Map<Member.City, List<String>>> collector3 = Collectors.groupingBy(classifier, collector2);
Map<Member.City, List<String>> mapByCity = totalStream.collect(collector3);

// same
Map<Member.City, List<String>> mapByCity = totalList.stream()
  .collect(
    Collectors.groupingBy(
      Member::getCity,
      Collectors.mapping(Member::getName, Collectors.toList())
    )
  );

// treemap
Map<Member.City, List<String>> mapByCity = totalList.stream()
  .collect(
    Collectors.groupingBy(
      Member::getCity,
      TreeMap::new,
      Collectors.mapping(Member::getName, Collectors.toList())
    )
  );

그룹핑 후 매핑 및 집계

Stream<Member> totalStream = totalList.stream();
Funtion<Member, Member.Sex> classifier = Member::getSex;
ToIntFunction<Member> mapper = Member::getAge;
Collector<Member, ?, Integer> collector1 = Collectors.averagingInt(mapper);
Collector<Member, ?, Map<Member.Sex, Integer>> collector2 = Collectors.groupingBy(classifier, collector1);
Map<Member.Sex, Integer> mapBySex = totalStream.collect(collector2);

// same
Map<Member.Sex, Integer> mapBySex = totalList.stream()
  .collect(
    Collectors.groupingBy(
      Member::getSex,
      Collectors.averagingInt(Member::getAge)
    )
  );

Map<Member.Sex, String> mapByName = totalList.stream()
  .collect(
    Collectors.groupingBy(
      Member::getSex,
      Collectors.mapping(
        Member::getName,
        Collectors.joining(",")
      )
    )
  );