Functional Idioms

Predicates class & Predicate interface

Iterables

all

any

find

filter

transform

Collections2

filter

transform

Lists

transform

Sets

filter

Maps

filterEntries

filterKeys

filterValues

uniqueIndex

transformValues

Iterables.filter(Iterable, Predicate)

FluentIterable.filter(Predicate)

Iterators.filter(Iterator, Predicate)

Collections2.filter(Collection, Predicate)

Sets.filter(Set, Predicate)

Sets.filter(SortedSet, Predicate)

Maps.filterKeys(Map, Predicate)

Maps.filterValues(Map, Predicate)

Maps.filterEntries(Map, Predicate)

Maps.filterKeys(SortedMap, Predicate)

Maps.filterValues(SortedMap, Predicate)

Maps.filterEntries(SortedMap, Predicate)

Multimaps.filterKeys(Multimap, Predicate)

Multimaps.filterValues(Multimap, Predicate)

Multimaps.filterEntries(Multimap, Predicate)

boolean all(Iterable, Predicate)

Iterators.all(Iterator, Predicate)

FluentIterable.allMatch(Predicate)

boolean any(Iterable, Predicate)

Iterators.any(Iterator, Predicate)

FluentIterable.anyMatch(Predicate)

T find(Iterable, Predicate)

Iterators.find(Iterator, Predicate)

Iterables.find(Iterable, Predicate, T default)

Iterators.find(Iterator, Predicate, T default)

Optional<T> tryFind(Iterable, Predicate)

Iterators.tryFind(Iterator, Predicate)

FluentIterable.firstMatch(Predicate)

indexOf(Iterable, Predicate)

Iterators.indexOf(Iterator, Predicate)

removeIf(Iterable, Predicate)

Iterators.removeIf(Iterator, Predicate)

Predicates

alwaysFlase 常にfalseを返す

alwaysTrue 常にtrueを返す

and 複数のPredicateを合わせた結果を返す

compose Functionの変換後の値をpredicateに渡す

equals 同じどうか

in collectionに含まれるかどうか

instanceOf クラスのインスタンスかどうか

isNull nullかどうか

not 結果を逆にする

notNull nullでないかどうか

or 複数のPredicateのいずれかがtrueの場合、trueを返す

Predicates.and(Iterable<Predicate<T>> predicates)

Predicates.and(Predicate<T>... predicates)

Predicate predicate = Predicates.and(aPredicate, bPredicate);

Predicates.or(Iterable<Predicate<T>> predicates)

Predicates.or(Predicate<T>... predicates)

Predicate predicate = Predicates.or(aPredicate, bPredicate);

Predicate predicate = Predicates.not(xPredicate);

Map<String, State> stateMap = ...;

Function<String,State> lookup = Functions.forMap(stateMap);

Predicate<String> predicate = Predicates.compose(xPredicate, lookup);

Functions class & Function interface

Iterables.transform(Iterable, Function)

FluentIterable.transform(Function)

Iterators.transform(Iterator, Function)

Collections2.transform(Collection, Function)

Lists.transform(List, Function)

Maps.transformValues(Map, Function)

Maps.transformEntries(Map, EntryTransformer)

Maps.transformValues(SortedMap, Function)

Maps.transformEntries(SortedMap, EntryTransformer)

Multimaps.transformValues(Multimap, Function)

Multimaps.transformEntries(Multimap, EntryTransformer)

Multimaps.transformValues(ListMultimap, Function)

Multimaps.transformEntries(ListMultimap, EntryTransformer)

Tables.transformValues(Table, Function)

Functions

compose 一つ目のFunctionの値を2つ目のFunctionの元にして値を返す

constant 常に一定の値を返す

forMap mapから値を取り出す

(値がnullの場合、IllegalArgumentException発生。デフォルト値指定可)

forPredicate Predicateの結果を返す

identity 変換元をそのまま返す

toStringFunction toString()した文字列を返す

Map<String, State> stateMap = ...;

Function<String,State> lookup = Functions.forMap(stateMap);

State state = lookup.apply("NY");

Function<State, String> stateFunction = new Function<State, String> {

@Override

public String apply(State input) {

return Joiner.on(",").join(input.getCities());

}

};

Function<String,String> composed =

Functions.compose(stateFunction, lookup);

String cities = composed.apply("NY");

あるいは

String cities = stateFunction.apply(lookup.apply("NY"));

Suppliers class & Supplier interface

private final LargeObject largeObject;

private Double average;

public Sample(LargeObject largeObject) {

this.largeObject = largeObject;

}

public Double calcAverage() {

if (average != null) {

return average;

}

// largeObjectに対する処理

return average;

}

import com.google.common.base.Supplier;

import com.google.common.base.Suppliers;

private final Supplier<Double> average;

public Sample(final LargeObject largeObject) {

Supplier<Double> supplier = new Supplier<Double>() {

@Override

public Double get() {

// largeObjectに対する処理

return average;

}

};

average = Suppliers.memoize(supplier);

}

public Double calcAverage() {

return average.get();

}

Supplier<Predicate<String>> supplier =

Suppliers.memoizeWithExpiration(xSupplier, 5L, TimeUnit.MINUTES);

サンプル1

List<Integer> list = Ints.asList(1, 2, 3, 4, 5);

Collection<Integer> evenList = Collections2.filter(list,

new Predicate<Integer>() {

@Override

public boolean apply(Integer input) {

return input % 2 == 0;

}

}

);

List<Integer> negativeList = Lists.transform(list,

new Function<Integer, Integer>() {

@Override

public Integer apply(Integer input) {

return -1 * input;

}

}

);

Collection<Employee> result = Collections2.filter(empList,

new Predicate<Employee>() {

@Override

public boolean apply(Employee emp) {

return emp.empNo <= 100;

}

}

);

Collection<String> result = Collections2.transform(empList,

new Function<Employee, String>() {

@Override

public String apply(Employee emp) {

return emp.name;

}

}

);

サンプル2

//書き方1

Function<String, Integer> lengthFunction = new Function<String, Integer>() {

public Integer apply(String string) {

return string.length();

}

};

Predicate<String> allCaps = new Predicate<String>() {

public boolean apply(String string) {

return CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string);

}

};

Multiset<Integer> lengths = HashMultiset.create(

Iterables.transform(Iterables.filter(strings, allCaps), lengthFunction)

);

//書き方2

Multiset<Integer> lengths = HashMultiset.create(

FluentIterable.from(strings)

.filter(new Predicate<String>() {

public boolean apply(String string) {

return CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string);

}

})

.transform(new Function<String, Integer>() {

public Integer apply(String string) {

return string.length();

}

})

);

//書き方3

Multiset<Integer> lengths = HashMultiset.create();

for (String string : strings) {

if (CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string)) {

lengths.add(string.length());

}

}

サンプル3

List<String> names;

Map<String, Person> personWithName;

List<Person> people

= Lists.transform(names, Functions.forMap(personWithName));

ListMultimap<String, String> firstNameToLastNames;

ListMultimap<String, String> firstNameToName =

Multimaps.transformEntries(firstNameToLastNames,

new EntryTransformer<String, String, String> () {

public String transformEntry(String firstName, String lastName) {

return firstName + " " + lastName;

}

}

);

注意点:Functionがシリアライズできないため

return Lists.transform(listA, new Function(...));

listB = Lists.transform(listA, new Function(...));

return Lists.newArrayList(listB);

あるいは

return ImmutableList.copyOf(listB);