How to use java.util.stream.Collector

table of contents

--Introduction --Create a Collector --Easy to use Collector --Collect Collectors --Generate from Collector


Introduction

--Since Java 8 Stream API is widely used instead of for statement --Stream has a set of termination processing, the representative of which is the collect method. --The argument of the collect method is java.util.stream.Collector


Make a Collector

//Collector to convert to ArrayList
Collector<T, ?, List<T>> toArrayList = Collector.of(
        ArrayList::new,
        List::add,
        (l1, l2) -> {
            l1.addAll(l2);
            return l1;
        },
        Characteristics.IDENTITY_FINISH);

//Run
.stream().collect(toArrayList);

There are many introductory articles on how to do this, so go there.


Stream conversion processing can be performed using Collector


Use Collector effortlessly

//Sample method
Stream<String> stream() {
  return Stream.of("1","20","30");
}
//Convert to List: [1, 20, 30]
stream().collect(toList());
//String concatenation: "<1,20,30>"
stream().collect(joining(",", "<", ">"));
//grouping: {1=[1], 2=[20, 30]}
stream().collect(groupingBy(String::length));
//List that cannot be changed
stream().collect(collectingAndThen(toList(), Collections::unmodifiableList));

Stream conversion can be done easily with Collectors


However, there are many articles that introduce Collector ...


result


User's voice

User A: Collector doesn't make that much User B: It's hard to call Collectors every time User C: I want Stream to have toList or toMap directly like other languages.

That's true, but collect is a slightly more generic method.


by the way

class Hoge {
	String methodA(String str) {
		if (str == null || str.equals("")) {
			return "A";
		}
		// ..
	}
	String methodB(String str) {
		if (str == null || str.equals("")) {
			return "B";
		}
		// ..
	}
}

What to do with this code?


Make it common (definition)

class StringUtil {
	boolean isEmpty(String str) {
		return str == null || str.equals("");
	}
}

Make it common (call)

class Hoge {
	String methodA(String str) {
		if (isEmpty(str)) {
			return "A";
		}
		// ..
	}
	String methodB(String str) {
		if (isEmpty(str)) {
			return "B";
		}
		// ..
	}
}

Then what is this?

String methodA(List<String> list) {
  list.stream()
    .map(/* ... */)
    .collect(collectingAndThen(toList(),Collections::unmodifiableList));
}
 
String methodB(List<String> list) {
  list.stream()
    .filter(/* ... */)
    .collect(collectingAndThen(toList(),Collections::unmodifiableList));
}

Make Collector common

//Collector utility class
class Collectors2 {
    //Returns a Collector that converts to an Unmodifiable List
  static <T> Collector<T,?,List<T>> toUnmodifiableList() {
    return collectingAndThen(toList(), Collections::unmodifiableList);
  }
}
//Use utility
stream()
    .collect(collectingAndThen(toList(),Collections::unmodifiableList));
// ↓
stream()
    .collect(toUnmodifiableList());

Since it is a method, the name is free

However, consideration must be given to comprehensibility


Usage example (Stream conversion)

class Collectors2 {
  //Group and Map.Collector that returns Stream of Entity
  static <T, K> Collector<T, ?, Stream<Map.Entry<K, List<T>>>> grouping(Function<T, K> mapper) {
    return collectingAndThen(
                groupingBy(mapper),
                m -> m.entrySet().stream()
        );
  }
}
//Group and convert to Stream again
stream()
    .collect(groupingBy(String::length)).entrySet().stream();
// ↓
stream()
    .collect(grouping(String::length));


Collect () becomes simple and versatile by preparing a utility for Collector like String.


Common processing

//Class with event history
@AllArgsConstructor
class History {
    List<String> events;
}

//Make a list of events
List<String> events = stream().collect(toList());
//Generate History
History history = new History(events);

Can create objects directly

List<String> events = stream().collect(toList());
History history = new History(events);

// ↓

//Convert directly to History
History history = stream()
    .collect(collectingAndThen(toList(), History::new));

collect is not just a method for generating Lists and Maps


Further combine

class Collectors2 {
  //After converting to List, return Collector that executes mapper function
    static <T, R> Collector<T, ?, R> toListAnd(Function<List<T>, R> mapper) {
    return collectingAndThen(toList(), mapper);
    }
}

//call
History history = stream()
  .collect(collectingAndThen(toList(), History::new));
// ↓
History history = stream()
  .collect(toListAnd(History::new));

Usage example (Optional conversion)

class Collectors2 {
  // toList()Optional if is empty.empty(), Optional if not empty<List<T>>return it
  static <T> Collector<T, ?, Optional<List<T>>> toOptionalList() {
    return collectingAndThen(toList(), l -> l.isEmpty() ? Optional.empty() : Optional.of(l));
  }
  //Execute the function with the list as an argument only when the List is not empty
  static <T, R> Collector<T, ?, Optional<R>> ifNotEmptyList(Function<List<T>, R> mapper) {
    return collectingAndThen(toOptionalList(), op -> op.map(mapper));
  }
}

//Generate History only when List is not empty
Optional<History> history = stream()
    .collect(ifNotEmptyList(History::new));

Usage example (Other)

//Convert to Json
stream
    .collect(toJson());
//Convert to CSV
stream
    .collect(toCsv());
//Convert to request parameter
stream
    .collect(toRequestParam());
//Convert to SQL
stream
    .collect(toSql());

Collectors can be reused by combining general-purpose Collectors.


For more practical usage

How to use gakuzzzz's Collector

-Synthesize Java8 Stream API Collector -How to use a certain Doma2

Utility class of Eclipse Collections (source is also helpful)


Summary

--Java 8 and later Stream is a frequent API --Collector is a part of where Stream is --The collect method is generic --Collectors can be combined and shared --Collector can be converted to your favorite object depending on how you use it


Enjoy collecting!!


reference

http://www.ne.jp/asahi/hishidama/home/tech/java/collector.html

Recommended Posts

How to use java.util.stream.Collector
How to use Map
How to use rbenv
How to use letter_opener_web
How to use with_option
How to use fields_for
How to use java.util.logging
How to use collection_select
How to use Twitter4J
How to use active_hash! !!
How to use MapStruct
How to use hidden_field_tag
How to use TreeSet
[How to use label]
How to use identity
How to use hashes
How to use Dozer.mapper
How to use Gradle
How to use org.immutables
How to use VisualVM
How to use Map
[Java] How to use Map
[Java] How to use Map
How to use Priority Queuing
[Rails] How to use enum
How to use java Optional
How to use JUnit (beginner)
How to use Ruby return
[Rails] How to use enum
[Swift] How to use UserDefaults
How to use java class
How to use Big Decimal
[Java] How to use Optional ②
[Java] How to use removeAll ()
How to use String [] args
[Java] How to use string.format
How to use rails join
How to use Java Map
Ruby: How to use cookies
How to use dependent :: destroy
How to use Eclipse Debug_Shell
How to use Apache POI
[Rails] How to use validation
How to use Java variables
[Rails] How to use authenticate_user!
[Rails] How to use "kaminari"
How to use GC Viewer
How to use Lombok now
[Creating] How to use JUnit
[Rails] How to use Scope
How to use the link_to method
[Rails] How to use gem "devise"
How to use Lombok in Spring
How to use StringBurrer and Arrays.toString.
How to use arrays (personal memorandum)
How to use Java HttpClient (Get)
How to use scope (JSP & Servlet)
How to use the include? method
[Rails] How to use devise (Note)
[Rails] How to use flash messages
How to use EventBus3 and ThreadMode