Functional idioms:Guava的函数习语可以大大简化代码。
1.注意事项
Java 8包括java.util.function
和java.util.stream
软件包,它们取代了Guava函数编程类,用于该语言级别的项目。
虽然Guava的函数工具类可在Java 8之前的Java版本上使用,但没有Java 8的函数式编程需要笨拙且冗长地使用匿名类。
过度使用Guava的函数式编程习语用法会导致冗长、混乱、不可读和低效的代码。这些是迄今为止最容易(也是最常见)的Guava滥用部分,当你费力地使代码变成"一行"时,Guava团队就会哭泣。
比较以下代码:
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.javaUpperCase().matchesAllOf(string);
}
};
Multiset<Integer> lengths = HashMultiset.create(
Iterables.transform(Iterables.filter(strings, allCaps), lengthFunction));
或流利的版本
Multiset<Integer> lengths = HashMultiset.create(
FluentIterable.from(strings)
.filter(new Predicate<String>() {
public boolean apply(String string) {
return CharMatcher.javaUpperCase().matchesAllOf(string);
}
})
.transform(new Function<String, Integer>() {
public Integer apply(String string) {
return string.length();
}
}));
同:
Multiset<Integer> lengths = HashMultiset.create();
for (String string : strings) {
if (CharMatcher.javaUpperCase().matchesAllOf(string)) {
lengths.add(string.length());
}
}
即使使用静态导入,甚至将Function
和Predicate
声明移至其它文件,第一个实现也不太简洁,可读性和效率较低。
命令式代码应该是默认选择,也是Java 7的第一选择。除非绝对确定以下其中一项,否则不应使用函数式用法:
- 使用函数式用法将节省整个项目的代码行。在上面的示例中,"函数式"版本使用11行,而命令式版本使用6行。将函数的定义移至另一个文件或常量中并没有帮助。
- 为了提高效率,你需要对转换后的集合进行延迟计算的视图,并且不能满足显式计算的集合。另外,你已经阅读并重新阅读了Effective Java,第55项,除了遵循这些说明之外,你实际上已经完成了基准测试以证明该版本更快,并且可以引用数字进行证明。
请确保在使用Guava的函数工具类时,传统的命令式处理方式并没有更好的可读性。试着写出来。真的那么糟糕吗?这比你将要尝试的笨拙的函数式方法更具可读性吗?
2.函数和谓语
本文仅讨论那些直接处理Function
和Predicate
的Guava功能。其它一些工具与“函数式”相关联,例如级联和可在恒定时间内返回视图的其它方法。尝试查看集合工具文章。
Guava提供了两个基本的"函数式"接口:
Function<A, B>
具有单个方法B apply(A input)
。通常希望Function
的实例具有参照透明性——无副作用——并且与equals一致,即a.equals(b)
表示function.apply(a).equals(function.apply(b))
。Predicate<T>
具有单个方法boolean apply(T input)
。通常希望Predicate
实例是无副作用的并且与equals一致。
3.特殊谓语
字符有自己的Predicate
的专用版本CharMatcher
,它通常对于这些需求而言更加高效和有用。CharMatcher
已经实现了Predicate<Character>
,可以相应地使用,而从Predicate
到CharMatcher
的转换可以使用CharMatcher.forPredicate
完成。有关详细信息,请参阅CharMatcher
文章 。
此外,对于可比较的类型和基于比较的谓语,可以使用Range
类型实现大多数需求,它实现了不可变的范围。Range
类型实现了Predicate
,测试是否包含在范围内。例如,Range.atMost(2)
是一个完全有效的Predicate<Integer>
。有关使用范围的更多详细信息参见[Range
文章]。
4.操作函数和谓语
Functions
中提供了简单的Function
构造和操作方法,包括:
有关详细信息,请查阅Javadoc。
Predicates
谓语中有很多可用的构造和操作方法,示例包括:
instanceOf(Class)
assignableFrom(Class)
contains(Pattern)
in(Collection)
isNull()
alwaysFalse()
,alwaysTrue()
equalTo(Object)
compose(Predicate, Function)
and(Predicate...)
,or(Predicate...)
,not(Predicate)
有关详细信息,请查阅Javadoc。
5.使用
Guava提供了许多使用函数和谓语来操作集合的工具。这些通常可以在集合工具类Iterables
,Lists
,Sets
,Maps
,Multimaps
等中找到。
6.谓语
谓语最基本的用途是过滤集合。所有Guava过滤器方法都返回视图。
集合类型 | 过滤方法 |
---|---|
Iterable | Iterables.filter(Iterable,Predicate)FluentIterable.filter(Predicate) |
7.使用示例
7.1Function
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.*;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.testing.ClassSanityTester;
import com.google.common.testing.EqualsTester;
import com.google.common.testing.NullPointerTester;
import com.google.common.testing.SerializableTester;
import junit.framework.TestCase;
import java.io.Serializable;
import java.util.Map;
public class FunctionsTest extends TestCase {
public void testIdentity_same() {
Function<String, String> identity = Functions.identity();
assertNull(identity.apply(null));
assertSame("foo", identity.apply("foo"));
}
public void testIdentity_notSame() {
Function<Long, Long> identity = Functions.identity();
assertNotSame(new Long(135135L), identity.apply(new Long(135135L)));
}
@GwtIncompatible // SerializableTester
public void testIdentitySerializable() {
checkCanReserializeSingleton(Functions.identity());
}
public void testToStringFunction_apply() {
assertEquals("3", Functions.toStringFunction().apply(3));
assertEquals("hiya", Functions.toStringFunction().apply("hiya"));
assertEquals(
"I'm a string",
Functions.toStringFunction()
.apply(
new Object() {
@Override
public String toString() {
return "I'm a string";
}
}));
try {
Functions.toStringFunction().apply(null);
fail("expected NullPointerException");
} catch (NullPointerException expected) {
}
}
@GwtIncompatible // SerializableTester
public void testToStringFunctionSerializable() {
checkCanReserializeSingleton(Functions.toStringFunction());
}
@GwtIncompatible // NullPointerTester
public void testNullPointerExceptions() {
NullPointerTester tester = new NullPointerTester();
tester.testAllPublicStaticMethods(Functions.class);
}
public void testForMapWithoutDefault() {
Map<String, Integer> map = Maps.newHashMap();
map.put("One", 1);
map.put("Three", 3);
map.put("Null", null);
Function<String, Integer> function = Functions.forMap(map);
assertEquals(1, function.apply("One").intValue());
assertEquals(3, function.apply("Three").intValue());
assertNull(function.apply("Null"));
try {
function.apply("Two");
fail();
} catch (IllegalArgumentException expected) {
}
new EqualsTester()
.addEqualityGroup(function, Functions.forMap(map))
.addEqualityGroup(Functions.forMap(map, 42))
.testEquals();
}
@GwtIncompatible // SerializableTester
public void testForMapWithoutDefaultSerializable() {
checkCanReserialize(Functions.forMap(ImmutableMap.of(1, 2)));
}
public void testForMapWithDefault() {
Map<String, Integer> map = Maps.newHashMap();
map.put("One", 1);
map.put("Three", 3);
map.put("Null", null);
Function<String, Integer> function = Functions.forMap(map, 42);
assertEquals(1, function.apply("One").intValue());
assertEquals(42, function.apply("Two").intValue());
assertEquals(3, function.apply("Three").intValue());
assertNull(function.apply("Null"));
new EqualsTester()
.addEqualityGroup(function, Functions.forMap(map, 42))
.addEqualityGroup(Functions.forMap(map))
.addEqualityGroup(Functions.forMap(map, null))
.addEqualityGroup(Functions.forMap(map, 43))
.testEquals();
}
@GwtIncompatible // SerializableTester
public void testForMapWithDefault_includeSerializable() {
Map<String, Integer> map = Maps.newHashMap();
map.put("One", 1);
map.put("Three", 3);
Function<String, Integer> function = Functions.forMap(map, 42);
assertEquals(1, function.apply("One").intValue());
assertEquals(42, function.apply("Two").intValue());
assertEquals(3, function.apply("Three").intValue());
new EqualsTester()
.addEqualityGroup(
function, Functions.forMap(map, 42), SerializableTester.reserialize(function))
.addEqualityGroup(Functions.forMap(map))
.addEqualityGroup(Functions.forMap(map, null))
.addEqualityGroup(Functions.forMap(map, 43))
.testEquals();
}
@GwtIncompatible // SerializableTester
public void testForMapWithDefaultSerializable() {
checkCanReserialize(Functions.forMap(ImmutableMap.of(1, 2), 3));
}
public void testForMapWithDefault_null() {
ImmutableMap<String, Integer> map = ImmutableMap.of("One", 1);
Function<String, Integer> function = Functions.forMap(map, null);
assertEquals((Integer) 1, function.apply("One"));
assertNull(function.apply("Two"));
// check basic sanity of equals and hashCode
new EqualsTester()
.addEqualityGroup(function)
.addEqualityGroup(Functions.forMap(map, 1))
.testEquals();
}
@GwtIncompatible // SerializableTester
public void testForMapWithDefault_null_compareWithSerializable() {
ImmutableMap<String, Integer> map = ImmutableMap.of("One", 1);
Function<String, Integer> function = Functions.forMap(map, null);
assertEquals((Integer) 1, function.apply("One"));
assertNull(function.apply("Two"));
// check basic sanity of equals and hashCode
new EqualsTester()
.addEqualityGroup(function, SerializableTester.reserialize(function))
.addEqualityGroup(Functions.forMap(map, 1))
.testEquals();
}
public void testForMapWildCardWithDefault() {
Map<String, Integer> map = Maps.newHashMap();
map.put("One", 1);
map.put("Three", 3);
Number number = Double.valueOf(42);
Function<String, Number> function = Functions.forMap(map, number);
assertEquals(1, function.apply("One").intValue());
assertEquals(number, function.apply("Two"));
assertEquals(3L, function.apply("Three").longValue());
}
public void testComposition() {
Map<String, Integer> mJapaneseToInteger = Maps.newHashMap();
mJapaneseToInteger.put("Ichi", 1);
mJapaneseToInteger.put("Ni", 2);
mJapaneseToInteger.put("San", 3);
Function<String, Integer> japaneseToInteger = Functions.forMap(mJapaneseToInteger);
Map<Integer, String> mIntegerToSpanish = Maps.newHashMap();
mIntegerToSpanish.put(1, "Uno");
mIntegerToSpanish.put(3, "Tres");
mIntegerToSpanish.put(4, "Cuatro");
Function<Integer, String> integerToSpanish = Functions.forMap(mIntegerToSpanish);
Function<String, String> japaneseToSpanish =
Functions.compose(integerToSpanish, japaneseToInteger);
assertEquals("Uno", japaneseToSpanish.apply("Ichi"));
try {
japaneseToSpanish.apply("Ni");
fail();
} catch (IllegalArgumentException e) {
}
assertEquals("Tres", japaneseToSpanish.apply("San"));
try {
japaneseToSpanish.apply("Shi");
fail();
} catch (IllegalArgumentException e) {
}
new EqualsTester()
.addEqualityGroup(japaneseToSpanish, Functions.compose(integerToSpanish, japaneseToInteger))
.addEqualityGroup(japaneseToInteger)
.addEqualityGroup(integerToSpanish)
.addEqualityGroup(Functions.compose(japaneseToInteger, integerToSpanish))
.testEquals();
}
@GwtIncompatible // SerializableTester
public void testComposition_includeReserializabled() {
Map<String, Integer> mJapaneseToInteger = Maps.newHashMap();
mJapaneseToInteger.put("Ichi", 1);
mJapaneseToInteger.put("Ni", 2);
mJapaneseToInteger.put("San", 3);
Function<String, Integer> japaneseToInteger = Functions.forMap(mJapaneseToInteger);
Map<Integer, String> mIntegerToSpanish = Maps.newHashMap();
mIntegerToSpanish.put(1, "Uno");
mIntegerToSpanish.put(3, "Tres");
mIntegerToSpanish.put(4, "Cuatro");
Function<Integer, String> integerToSpanish = Functions.forMap(mIntegerToSpanish);
Function<String, String> japaneseToSpanish =
Functions.compose(integerToSpanish, japaneseToInteger);
new EqualsTester()
.addEqualityGroup(
japaneseToSpanish,
Functions.compose(integerToSpanish, japaneseToInteger),
SerializableTester.reserialize(japaneseToSpanish))
.addEqualityGroup(japaneseToInteger)
.addEqualityGroup(integerToSpanish)
.addEqualityGroup(Functions.compose(japaneseToInteger, integerToSpanish))
.testEquals();
}
public void testCompositionWildcard() {
Map<String, Integer> mapJapaneseToInteger = Maps.newHashMap();
Function<String, Integer> japaneseToInteger = Functions.forMap(mapJapaneseToInteger);
Function<Object, String> numberToSpanish = Functions.constant("Yo no se");
Function<String, String> japaneseToSpanish =
Functions.compose(numberToSpanish, japaneseToInteger);
}
private static class HashCodeFunction implements Function<Object, Integer> {
@Override
public Integer apply(Object o) {
return (o == null) ? 0 : o.hashCode();
}
}
public void testComposeOfFunctionsIsAssociative() {
Map<Float, String> m = ImmutableMap.of(4.0f, "A", 3.0f, "B", 2.0f, "C", 1.0f, "D");
Function<? super Integer, Boolean> h = Functions.constant(Boolean.TRUE);
Function<? super String, Integer> g = new HashCodeFunction();
Function<Float, String> f = Functions.forMap(m, "F");
Function<Float, Boolean> c1 = Functions.compose(Functions.compose(h, g), f);
Function<Float, Boolean> c2 = Functions.compose(h, Functions.compose(g, f));
// Might be nice (eventually) to have:
// assertEquals(c1, c2);
// But for now, settle for this:
assertEquals(c1.hashCode(), c2.hashCode());
assertEquals(c1.apply(1.0f), c2.apply(1.0f));
assertEquals(c1.apply(5.0f), c2.apply(5.0f));
}
public void testComposeOfPredicateAndFunctionIsAssociative() {
Map<Float, String> m = ImmutableMap.of(4.0f, "A", 3.0f, "B", 2.0f, "C", 1.0f, "D");
Predicate<? super Integer> h = Predicates.equalTo(42);
Function<? super String, Integer> g = new HashCodeFunction();
Function<Float, String> f = Functions.forMap(m, "F");
Predicate<Float> p1 = Predicates.compose(Predicates.compose(h, g), f);
Predicate<Float> p2 = Predicates.compose(h, Functions.compose(g, f));
// Might be nice (eventually) to have:
// assertEquals(p1, p2);
// But for now, settle for this:
assertEquals(p1.hashCode(), p2.hashCode());
assertEquals(p1.apply(1.0f), p2.apply(1.0f));
assertEquals(p1.apply(5.0f), p2.apply(5.0f));
}
public void testForPredicate() {
Function<Object, Boolean> alwaysTrue = Functions.forPredicate(Predicates.alwaysTrue());
Function<Object, Boolean> alwaysFalse = Functions.forPredicate(Predicates.alwaysFalse());
assertTrue(alwaysTrue.apply(0));
assertFalse(alwaysFalse.apply(0));
new EqualsTester()
.addEqualityGroup(alwaysTrue, Functions.forPredicate(Predicates.alwaysTrue()))
.addEqualityGroup(alwaysFalse)
.addEqualityGroup(Functions.identity())
.testEquals();
}
@GwtIncompatible // SerializableTester
public void testForPredicateSerializable() {
checkCanReserialize(Functions.forPredicate(Predicates.equalTo(5)));
}
public void testConstant() {
Function<Object, Object> f = Functions.<Object>constant("correct");
assertEquals("correct", f.apply(new Object()));
assertEquals("correct", f.apply(null));
Function<Object, String> g = Functions.constant(null);
assertEquals(null, g.apply(2));
assertEquals(null, g.apply(null));
new EqualsTester()
.addEqualityGroup(f, Functions.constant("correct"))
.addEqualityGroup(Functions.constant("incorrect"))
.addEqualityGroup(Functions.toStringFunction())
.addEqualityGroup(g)
.testEquals();
new EqualsTester()
.addEqualityGroup(g, Functions.constant(null))
.addEqualityGroup(Functions.constant("incorrect"))
.addEqualityGroup(Functions.toStringFunction())
.addEqualityGroup(f)
.testEquals();
}
@GwtIncompatible // SerializableTester
public void testConstantSerializable() {
checkCanReserialize(Functions.constant(5));
}
private static class CountingSupplier implements Supplier<Integer>, Serializable {
private static final long serialVersionUID = 0;
private int value;
@Override
public Integer get() {
return ++value;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof CountingSupplier) {
return this.value == ((CountingSupplier) obj).value;
}
return false;
}
@Override
public int hashCode() {
return value;
}
}
public void testForSupplier() {
Supplier<Integer> supplier = new CountingSupplier();
Function<Object, Integer> function = Functions.forSupplier(supplier);
assertEquals(1, (int) function.apply(null));
assertEquals(2, (int) function.apply("foo"));
new EqualsTester()
.addEqualityGroup(function, Functions.forSupplier(supplier))
.addEqualityGroup(Functions.forSupplier(new CountingSupplier()))
.addEqualityGroup(Functions.forSupplier(Suppliers.ofInstance(12)))
.addEqualityGroup(Functions.toStringFunction())
.testEquals();
}
@GwtIncompatible // SerializableTester
public void testForSupplierSerializable() {
checkCanReserialize(Functions.forSupplier(new CountingSupplier()));
}
@GwtIncompatible // reflection
public void testNulls() throws Exception {
new ClassSanityTester().forAllPublicStaticMethods(Functions.class).testNulls();
}
@GwtIncompatible // reflection
// (I suspect that this and the other similar failures happen with ArbitraryInstances proxies.)
public void testEqualsAndSerializable() throws Exception {
new ClassSanityTester().forAllPublicStaticMethods(Functions.class).testEqualsAndSerializable();
}
@GwtIncompatible // SerializableTester
private static <Y> void checkCanReserialize(Function<? super Integer, Y> f) {
Function<? super Integer, Y> g = SerializableTester.reserializeAndAssert(f);
for (int i = 1; i < 5; i++) {
// convoluted way to check that the same result happens from each
Y expected = null;
try {
expected = f.apply(i);
} catch (IllegalArgumentException e) {
try {
g.apply(i);
fail();
} catch (IllegalArgumentException ok) {
continue;
}
}
assertEquals(expected, g.apply(i));
}
}
@GwtIncompatible // SerializableTester
private static <Y> void checkCanReserializeSingleton(Function<? super String, Y> f) {
Function<? super String, Y> g = SerializableTester.reserializeAndAssert(f);
assertSame(f, g);
for (Integer i = 1; i < 5; i++) {
assertEquals(f.apply(i.toString()), g.apply(i.toString()));
}
}
}
7.2Predicate
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.*;
import com.google.common.collect.ImmutableSet;
import com.google.common.testing.ClassSanityTester;
import com.google.common.testing.EqualsTester;
import com.google.common.testing.NullPointerTester;
import com.google.common.testing.SerializableTester;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import java.io.Serializable;
import java.util.*;
import java.util.regex.Pattern;
import static com.google.common.base.CharMatcher.whitespace;
import static com.google.common.collect.Lists.newArrayList;
public class PredicatesTest extends TestCase {
private static final Predicate<Integer> TRUE = Predicates.alwaysTrue();
private static final Predicate<Integer> FALSE = Predicates.alwaysFalse();
private static final Predicate<Integer> NEVER_REACHED =
new Predicate<Integer>() {
@Override
public boolean apply(Integer i) {
throw new AssertionFailedError("This predicate should never have been evaluated");
}
};
/**
* Instantiable predicate with reasonable hashCode() and equals() methods.
*/
static class IsOdd implements Predicate<Integer>, Serializable {
private static final long serialVersionUID = 0x150ddL;
@Override
public boolean apply(Integer i) {
return (i.intValue() & 1) == 1;
}
@Override
public int hashCode() {
return 0x150dd;
}
@Override
public boolean equals(Object obj) {
return obj instanceof IsOdd;
}
@Override
public String toString() {
return "IsOdd";
}
}
/**
* Generates a new Predicate per call.
*
* <p>Creating a new Predicate each time helps catch cases where code is using {@code x == y}
* instead of {@code x.equals(y)}.
*/
private static IsOdd isOdd() {
return new IsOdd();
}
/*
* Tests for Predicates.alwaysTrue().
*/
public void testAlwaysTrue_apply() {
assertEvalsToTrue(Predicates.alwaysTrue());
}
public void testAlwaysTrue_equality() throws Exception {
new EqualsTester()
.addEqualityGroup(TRUE, Predicates.alwaysTrue())
.addEqualityGroup(isOdd())
.addEqualityGroup(Predicates.alwaysFalse())
.testEquals();
}
@GwtIncompatible // SerializableTester
public void testAlwaysTrue_serialization() {
checkSerialization(Predicates.alwaysTrue());
}
/*
* Tests for Predicates.alwaysFalse().
*/
public void testAlwaysFalse_apply() throws Exception {
assertEvalsToFalse(Predicates.alwaysFalse());
}
public void testAlwaysFalse_equality() throws Exception {
new EqualsTester()
.addEqualityGroup(FALSE, Predicates.alwaysFalse())
.addEqualityGroup(isOdd())
.addEqualityGroup(Predicates.alwaysTrue())
.testEquals();
}
@GwtIncompatible // SerializableTester
public void testAlwaysFalse_serialization() {
checkSerialization(Predicates.alwaysFalse());
}
/*
* Tests for Predicates.not(predicate).
*/
public void testNot_apply() {
assertEvalsToTrue(Predicates.not(FALSE));
assertEvalsToFalse(Predicates.not(TRUE));
assertEvalsLikeOdd(Predicates.not(Predicates.not(isOdd())));
}
public void testNot_equality() {
new EqualsTester()
.addEqualityGroup(Predicates.not(isOdd()), Predicates.not(isOdd()))
.addEqualityGroup(Predicates.not(TRUE))
.addEqualityGroup(isOdd())
.testEquals();
}
public void testNot_equalityForNotOfKnownValues() {
new EqualsTester()
.addEqualityGroup(TRUE, Predicates.alwaysTrue())
.addEqualityGroup(FALSE)
.addEqualityGroup(Predicates.not(TRUE))
.testEquals();
new EqualsTester()
.addEqualityGroup(FALSE, Predicates.alwaysFalse())
.addEqualityGroup(TRUE)
.addEqualityGroup(Predicates.not(FALSE))
.testEquals();
new EqualsTester()
.addEqualityGroup(Predicates.isNull(), Predicates.isNull())
.addEqualityGroup(Predicates.notNull())
.addEqualityGroup(Predicates.not(Predicates.isNull()))
.testEquals();
new EqualsTester()
.addEqualityGroup(Predicates.notNull(), Predicates.notNull())
.addEqualityGroup(Predicates.isNull())
.addEqualityGroup(Predicates.not(Predicates.notNull()))
.testEquals();
}
@GwtIncompatible // SerializableTester
public void testNot_serialization() {
checkSerialization(Predicates.not(isOdd()));
}
/*
* Tests for all the different flavors of Predicates.and().
*/
@SuppressWarnings("unchecked") // varargs
public void testAnd_applyNoArgs() {
assertEvalsToTrue(Predicates.and());
}
@SuppressWarnings("unchecked") // varargs
public void testAnd_equalityNoArgs() {
new EqualsTester()
.addEqualityGroup(Predicates.and(), Predicates.and())
.addEqualityGroup(Predicates.and(FALSE))
.addEqualityGroup(Predicates.or())
.testEquals();
}
@GwtIncompatible // SerializableTester
@SuppressWarnings("unchecked") // varargs
public void testAnd_serializationNoArgs() {
checkSerialization(Predicates.and());
}
@SuppressWarnings("unchecked") // varargs
public void testAnd_applyOneArg() {
assertEvalsLikeOdd(Predicates.and(isOdd()));
}
@SuppressWarnings("unchecked") // varargs
public void testAnd_equalityOneArg() {
Object[] notEqualObjects = {Predicates.and(NEVER_REACHED, FALSE)};
new EqualsTester()
.addEqualityGroup(Predicates.and(NEVER_REACHED), Predicates.and(NEVER_REACHED))
.addEqualityGroup(notEqualObjects)
.addEqualityGroup(Predicates.and(isOdd()))
.addEqualityGroup(Predicates.and())
.addEqualityGroup(Predicates.or(NEVER_REACHED))
.testEquals();
}
@GwtIncompatible // SerializableTester
@SuppressWarnings("unchecked") // varargs
public void testAnd_serializationOneArg() {
checkSerialization(Predicates.and(isOdd()));
}
public void testAnd_applyBinary() {
assertEvalsLikeOdd(Predicates.and(isOdd(), TRUE));
assertEvalsLikeOdd(Predicates.and(TRUE, isOdd()));
assertEvalsToFalse(Predicates.and(FALSE, NEVER_REACHED));
}
@SuppressWarnings("unchecked") // varargs
public void testAnd_equalityBinary() {
new EqualsTester()
.addEqualityGroup(Predicates.and(TRUE, NEVER_REACHED), Predicates.and(TRUE, NEVER_REACHED))
.addEqualityGroup(Predicates.and(NEVER_REACHED, TRUE))
.addEqualityGroup(Predicates.and(TRUE))
.addEqualityGroup(Predicates.or(TRUE, NEVER_REACHED))
.testEquals();
}
@GwtIncompatible // SerializableTester
public void testAnd_serializationBinary() {
checkSerialization(Predicates.and(TRUE, isOdd()));
}
@SuppressWarnings("unchecked") // varargs
public void testAnd_applyTernary() {
assertEvalsLikeOdd(Predicates.and(isOdd(), TRUE, TRUE));
assertEvalsLikeOdd(Predicates.and(TRUE, isOdd(), TRUE));
assertEvalsLikeOdd(Predicates.and(TRUE, TRUE, isOdd()));
assertEvalsToFalse(Predicates.and(TRUE, FALSE, NEVER_REACHED));
}
@SuppressWarnings("unchecked") // varargs
public void testAnd_equalityTernary() {
new EqualsTester()
.addEqualityGroup(
Predicates.and(TRUE, isOdd(), NEVER_REACHED),
Predicates.and(TRUE, isOdd(), NEVER_REACHED))
.addEqualityGroup(Predicates.and(isOdd(), NEVER_REACHED, TRUE))
.addEqualityGroup(Predicates.and(TRUE))
.addEqualityGroup(Predicates.or(TRUE, isOdd(), NEVER_REACHED))
.testEquals();
}
@GwtIncompatible // SerializableTester
@SuppressWarnings("unchecked") // varargs
public void testAnd_serializationTernary() {
checkSerialization(Predicates.and(TRUE, isOdd(), FALSE));
}
@SuppressWarnings("unchecked") // varargs
public void testAnd_applyIterable() {
Collection<Predicate<Integer>> empty = Arrays.asList();
assertEvalsToTrue(Predicates.and(empty));
assertEvalsLikeOdd(Predicates.and(Arrays.asList(isOdd())));
assertEvalsLikeOdd(Predicates.and(Arrays.asList(TRUE, isOdd())));
assertEvalsToFalse(Predicates.and(Arrays.asList(FALSE, NEVER_REACHED)));
}
@SuppressWarnings("unchecked") // varargs
public void testAnd_equalityIterable() {
new EqualsTester()
.addEqualityGroup(
Predicates.and(Arrays.asList(TRUE, NEVER_REACHED)),
Predicates.and(Arrays.asList(TRUE, NEVER_REACHED)),
Predicates.and(TRUE, NEVER_REACHED))
.addEqualityGroup(Predicates.and(FALSE, NEVER_REACHED))
.addEqualityGroup(Predicates.or(TRUE, NEVER_REACHED))
.testEquals();
}
@GwtIncompatible // SerializableTester
@SuppressWarnings("unchecked") // varargs
public void testAnd_serializationIterable() {
checkSerialization(Predicates.and(Arrays.asList(TRUE, FALSE)));
}
@SuppressWarnings("unchecked") // varargs
public void testAnd_arrayDefensivelyCopied() {
Predicate[] array = {Predicates.alwaysFalse()};
Predicate<Object> predicate = Predicates.and(array);
assertFalse(predicate.apply(1));
array[0] = Predicates.alwaysTrue();
assertFalse(predicate.apply(1));
}
public void testAnd_listDefensivelyCopied() {
List<Predicate<Object>> list = newArrayList();
Predicate<Object> predicate = Predicates.and(list);
assertTrue(predicate.apply(1));
list.add(Predicates.alwaysFalse());
assertTrue(predicate.apply(1));
}
public void testAnd_iterableDefensivelyCopied() {
final List<Predicate<Object>> list = newArrayList();
Iterable<Predicate<Object>> iterable =
new Iterable<Predicate<Object>>() {
@Override
public Iterator<Predicate<Object>> iterator() {
return list.iterator();
}
};
Predicate<Object> predicate = Predicates.and(iterable);
assertTrue(predicate.apply(1));
list.add(Predicates.alwaysFalse());
assertTrue(predicate.apply(1));
}
/*
* Tests for all the different flavors of Predicates.or().
*/
@SuppressWarnings("unchecked") // varargs
public void testOr_applyNoArgs() {
assertEvalsToFalse(Predicates.or());
}
@SuppressWarnings("unchecked") // varargs
public void testOr_equalityNoArgs() {
new EqualsTester()
.addEqualityGroup(Predicates.or(), Predicates.or())
.addEqualityGroup(Predicates.or(TRUE))
.addEqualityGroup(Predicates.and())
.testEquals();
}
@GwtIncompatible // SerializableTester
@SuppressWarnings("unchecked") // varargs
public void testOr_serializationNoArgs() {
checkSerialization(Predicates.or());
}
@SuppressWarnings("unchecked") // varargs
public void testOr_applyOneArg() {
assertEvalsToTrue(Predicates.or(TRUE));
assertEvalsToFalse(Predicates.or(FALSE));
}
@SuppressWarnings("unchecked") // varargs
public void testOr_equalityOneArg() {
new EqualsTester()
.addEqualityGroup(Predicates.or(NEVER_REACHED), Predicates.or(NEVER_REACHED))
.addEqualityGroup(Predicates.or(NEVER_REACHED, TRUE))
.addEqualityGroup(Predicates.or(TRUE))
.addEqualityGroup(Predicates.or())
.addEqualityGroup(Predicates.and(NEVER_REACHED))
.testEquals();
}
@GwtIncompatible // SerializableTester
@SuppressWarnings("unchecked") // varargs
public void testOr_serializationOneArg() {
checkSerialization(Predicates.or(isOdd()));
}
public void testOr_applyBinary() {
Predicate<Integer> falseOrFalse = Predicates.or(FALSE, FALSE);
Predicate<Integer> falseOrTrue = Predicates.or(FALSE, TRUE);
Predicate<Integer> trueOrAnything = Predicates.or(TRUE, NEVER_REACHED);
assertEvalsToFalse(falseOrFalse);
assertEvalsToTrue(falseOrTrue);
assertEvalsToTrue(trueOrAnything);
}
@SuppressWarnings("unchecked") // varargs
public void testOr_equalityBinary() {
new EqualsTester()
.addEqualityGroup(Predicates.or(FALSE, NEVER_REACHED), Predicates.or(FALSE, NEVER_REACHED))
.addEqualityGroup(Predicates.or(NEVER_REACHED, FALSE))
.addEqualityGroup(Predicates.or(TRUE))
.addEqualityGroup(Predicates.and(FALSE, NEVER_REACHED))
.testEquals();
}
@GwtIncompatible // SerializableTester
public void testOr_serializationBinary() {
checkSerialization(Predicates.or(isOdd(), TRUE));
}
@SuppressWarnings("unchecked") // varargs
public void testOr_applyTernary() {
assertEvalsLikeOdd(Predicates.or(isOdd(), FALSE, FALSE));
assertEvalsLikeOdd(Predicates.or(FALSE, isOdd(), FALSE));
assertEvalsLikeOdd(Predicates.or(FALSE, FALSE, isOdd()));
assertEvalsToTrue(Predicates.or(FALSE, TRUE, NEVER_REACHED));
}
@SuppressWarnings("unchecked") // varargs
public void testOr_equalityTernary() {
new EqualsTester()
.addEqualityGroup(
Predicates.or(FALSE, NEVER_REACHED, TRUE), Predicates.or(FALSE, NEVER_REACHED, TRUE))
.addEqualityGroup(Predicates.or(TRUE, NEVER_REACHED, FALSE))
.addEqualityGroup(Predicates.or(TRUE))
.addEqualityGroup(Predicates.and(FALSE, NEVER_REACHED, TRUE))
.testEquals();
}
@GwtIncompatible // SerializableTester
@SuppressWarnings("unchecked") // varargs
public void testOr_serializationTernary() {
checkSerialization(Predicates.or(FALSE, isOdd(), TRUE));
}
@SuppressWarnings("unchecked") // varargs
public void testOr_applyIterable() {
Predicate<Integer> vacuouslyFalse = Predicates.or(Collections.<Predicate<Integer>>emptyList());
Predicate<Integer> troo = Predicates.or(Collections.singletonList(TRUE));
/*
* newLinkedList() takes varargs. TRUE and FALSE are both instances of
* Predicate<Integer>, so the call is safe.
*/
Predicate<Integer> trueAndFalse = Predicates.or(Arrays.asList(TRUE, FALSE));
assertEvalsToFalse(vacuouslyFalse);
assertEvalsToTrue(troo);
assertEvalsToTrue(trueAndFalse);
}
@SuppressWarnings("unchecked") // varargs
public void testOr_equalityIterable() {
new EqualsTester()
.addEqualityGroup(
Predicates.or(Arrays.asList(FALSE, NEVER_REACHED)),
Predicates.or(Arrays.asList(FALSE, NEVER_REACHED)),
Predicates.or(FALSE, NEVER_REACHED))
.addEqualityGroup(Predicates.or(TRUE, NEVER_REACHED))
.addEqualityGroup(Predicates.and(FALSE, NEVER_REACHED))
.testEquals();
}
@GwtIncompatible // SerializableTester
@SuppressWarnings("unchecked") // varargs
public void testOr_serializationIterable() {
Predicate<Integer> pre = Predicates.or(Arrays.asList(TRUE, FALSE));
Predicate<Integer> post = SerializableTester.reserializeAndAssert(pre);
assertEquals(pre.apply(0), post.apply(0));
}
@SuppressWarnings("unchecked") // varargs
public void testOr_arrayDefensivelyCopied() {
Predicate[] array = {Predicates.alwaysFalse()};
Predicate<Object> predicate = Predicates.or(array);
assertFalse(predicate.apply(1));
array[0] = Predicates.alwaysTrue();
assertFalse(predicate.apply(1));
}
public void testOr_listDefensivelyCopied() {
List<Predicate<Object>> list = newArrayList();
Predicate<Object> predicate = Predicates.or(list);
assertFalse(predicate.apply(1));
list.add(Predicates.alwaysTrue());
assertFalse(predicate.apply(1));
}
public void testOr_iterableDefensivelyCopied() {
final List<Predicate<Object>> list = newArrayList();
Iterable<Predicate<Object>> iterable =
new Iterable<Predicate<Object>>() {
@Override
public Iterator<Predicate<Object>> iterator() {
return list.iterator();
}
};
Predicate<Object> predicate = Predicates.or(iterable);
assertFalse(predicate.apply(1));
list.add(Predicates.alwaysTrue());
assertFalse(predicate.apply(1));
}
/*
* Tests for Predicates.equalTo(x).
*/
public void testIsEqualTo_apply() {
Predicate<Integer> isOne = Predicates.equalTo(1);
assertTrue(isOne.apply(1));
assertFalse(isOne.apply(2));
assertFalse(isOne.apply(null));
}
public void testIsEqualTo_equality() {
new EqualsTester()
.addEqualityGroup(Predicates.equalTo(1), Predicates.equalTo(1))
.addEqualityGroup(Predicates.equalTo(2))
.addEqualityGroup(Predicates.equalTo(null))
.testEquals();
}
@GwtIncompatible // SerializableTester
public void testIsEqualTo_serialization() {
checkSerialization(Predicates.equalTo(1));
}
public void testIsEqualToNull_apply() {
Predicate<Integer> isNull = Predicates.equalTo(null);
assertTrue(isNull.apply(null));
assertFalse(isNull.apply(1));
}
public void testIsEqualToNull_equality() {
new EqualsTester()
.addEqualityGroup(Predicates.equalTo(null), Predicates.equalTo(null))
.addEqualityGroup(Predicates.equalTo(1))
.addEqualityGroup(Predicates.equalTo("null"))
.testEquals();
}
@GwtIncompatible // SerializableTester
public void testIsEqualToNull_serialization() {
checkSerialization(Predicates.equalTo(null));
}
/**
* Tests for Predicates.instanceOf(x). TODO: Fix the comment style after fixing annotation
* stripper to remove comments properly. Currently, all tests before the comments are removed as
* well.
*/
@GwtIncompatible // Predicates.instanceOf
public void testIsInstanceOf_apply() {
Predicate<Object> isInteger = Predicates.instanceOf(Integer.class);
assertTrue(isInteger.apply(1));
assertFalse(isInteger.apply(2.0f));
assertFalse(isInteger.apply(""));
assertFalse(isInteger.apply(null));
}
@GwtIncompatible // Predicates.instanceOf
public void testIsInstanceOf_subclass() {
Predicate<Object> isNumber = Predicates.instanceOf(Number.class);
assertTrue(isNumber.apply(1));
assertTrue(isNumber.apply(2.0f));
assertFalse(isNumber.apply(""));
assertFalse(isNumber.apply(null));
}
@GwtIncompatible // Predicates.instanceOf
public void testIsInstanceOf_interface() {
Predicate<Object> isComparable = Predicates.instanceOf(Comparable.class);
assertTrue(isComparable.apply(1));
assertTrue(isComparable.apply(2.0f));
assertTrue(isComparable.apply(""));
assertFalse(isComparable.apply(null));
}
@GwtIncompatible // Predicates.instanceOf
public void testIsInstanceOf_equality() {
new EqualsTester()
.addEqualityGroup(
Predicates.instanceOf(Integer.class), Predicates.instanceOf(Integer.class))
.addEqualityGroup(Predicates.instanceOf(Number.class))
.addEqualityGroup(Predicates.instanceOf(Float.class))
.testEquals();
}
@GwtIncompatible // Predicates.instanceOf, SerializableTester
public void testIsInstanceOf_serialization() {
checkSerialization(Predicates.instanceOf(Integer.class));
}
@GwtIncompatible // Predicates.subtypeOf
public void testSubtypeOf_apply() {
Predicate<Class<?>> isInteger = Predicates.subtypeOf(Integer.class);
assertTrue(isInteger.apply(Integer.class));
assertFalse(isInteger.apply(Float.class));
try {
isInteger.apply(null);
fail();
} catch (NullPointerException expected) {
}
}
@GwtIncompatible // Predicates.subtypeOf
public void testSubtypeOf_subclass() {
Predicate<Class<?>> isNumber = Predicates.subtypeOf(Number.class);
assertTrue(isNumber.apply(Integer.class));
assertTrue(isNumber.apply(Float.class));
}
@GwtIncompatible // Predicates.subtypeOf
public void testSubtypeOf_interface() {
Predicate<Class<?>> isComparable = Predicates.subtypeOf(Comparable.class);
assertTrue(isComparable.apply(Integer.class));
assertTrue(isComparable.apply(Float.class));
}
@GwtIncompatible // Predicates.subtypeOf
public void testSubtypeOf_equality() {
new EqualsTester()
.addEqualityGroup(Predicates.subtypeOf(Integer.class))
.addEqualityGroup(Predicates.subtypeOf(Number.class))
.addEqualityGroup(Predicates.subtypeOf(Float.class))
.testEquals();
}
@GwtIncompatible // Predicates.subtypeOf, SerializableTester
public void testSubtypeOf_serialization() {
Predicate<Class<?>> predicate = Predicates.subtypeOf(Integer.class);
Predicate<Class<?>> reserialized = SerializableTester.reserializeAndAssert(predicate);
assertEvalsLike(predicate, reserialized, Integer.class);
assertEvalsLike(predicate, reserialized, Float.class);
assertEvalsLike(predicate, reserialized, null);
}
/*
* Tests for Predicates.isNull()
*/
public void testIsNull_apply() {
Predicate<Integer> isNull = Predicates.isNull();
assertTrue(isNull.apply(null));
assertFalse(isNull.apply(1));
}
public void testIsNull_equality() {
new EqualsTester()
.addEqualityGroup(Predicates.isNull(), Predicates.isNull())
.addEqualityGroup(Predicates.notNull())
.testEquals();
}
@GwtIncompatible // SerializableTester
public void testIsNull_serialization() {
Predicate<String> pre = Predicates.isNull();
Predicate<String> post = SerializableTester.reserializeAndAssert(pre);
assertEquals(pre.apply("foo"), post.apply("foo"));
assertEquals(pre.apply(null), post.apply(null));
}
public void testNotNull_apply() {
Predicate<Integer> notNull = Predicates.notNull();
assertFalse(notNull.apply(null));
assertTrue(notNull.apply(1));
}
public void testNotNull_equality() {
new EqualsTester()
.addEqualityGroup(Predicates.notNull(), Predicates.notNull())
.addEqualityGroup(Predicates.isNull())
.testEquals();
}
@GwtIncompatible // SerializableTester
public void testNotNull_serialization() {
checkSerialization(Predicates.notNull());
}
public void testIn_apply() {
Collection<Integer> nums = Arrays.asList(1, 5);
Predicate<Integer> isOneOrFive = Predicates.in(nums);
assertTrue(isOneOrFive.apply(1));
assertTrue(isOneOrFive.apply(5));
assertFalse(isOneOrFive.apply(3));
assertFalse(isOneOrFive.apply(null));
}
public void testIn_equality() {
Collection<Integer> nums = ImmutableSet.of(1, 5);
Collection<Integer> sameOrder = ImmutableSet.of(1, 5);
Collection<Integer> differentOrder = ImmutableSet.of(5, 1);
Collection<Integer> differentNums = ImmutableSet.of(1, 3, 5);
new EqualsTester()
.addEqualityGroup(
Predicates.in(nums),
Predicates.in(nums),
Predicates.in(sameOrder),
Predicates.in(differentOrder))
.addEqualityGroup(Predicates.in(differentNums))
.testEquals();
}
@GwtIncompatible // SerializableTester
public void testIn_serialization() {
checkSerialization(Predicates.in(Arrays.asList(1, 2, 3, null)));
}
public void testIn_handlesNullPointerException() {
class CollectionThatThrowsNPE<T> extends ArrayList<T> {
private static final long serialVersionUID = 1L;
@Override
public boolean contains(Object element) {
Preconditions.checkNotNull(element);
return super.contains(element);
}
}
Collection<Integer> nums = new CollectionThatThrowsNPE<>();
Predicate<Integer> isFalse = Predicates.in(nums);
assertFalse(isFalse.apply(null));
}
public void testIn_handlesClassCastException() {
class CollectionThatThrowsCCE<T> extends ArrayList<T> {
private static final long serialVersionUID = 1L;
@Override
public boolean contains(Object element) {
throw new ClassCastException("");
}
}
Collection<Integer> nums = new CollectionThatThrowsCCE<>();
nums.add(3);
Predicate<Integer> isThree = Predicates.in(nums);
assertFalse(isThree.apply(3));
}
/*
* Tests that compilation will work when applying explicit types.
*/
@SuppressWarnings("unused") // compilation test
public void testIn_compilesWithExplicitSupertype() {
Collection<Number> nums = ImmutableSet.of();
Predicate<Number> p1 = Predicates.in(nums);
Predicate<Object> p2 = Predicates.<Object>in(nums);
// The next two lines are not expected to compile.
// Predicate<Integer> p3 = Predicates.in(nums);
// Predicate<Integer> p4 = Predicates.<Integer>in(nums);
}
@GwtIncompatible // NullPointerTester
public void testNullPointerExceptions() {
NullPointerTester tester = new NullPointerTester();
tester.testAllPublicStaticMethods(Predicates.class);
}
@SuppressWarnings("unchecked") // varargs
@GwtIncompatible // SerializbleTester
public void testCascadingSerialization() throws Exception {
// Eclipse says Predicate<Integer>; javac says Predicate<Object>.
Predicate<? super Integer> nasty =
Predicates.not(
Predicates.and(
Predicates.or(
Predicates.equalTo((Object) 1),
Predicates.equalTo(null),
Predicates.alwaysFalse(),
Predicates.alwaysTrue(),
Predicates.isNull(),
Predicates.notNull(),
Predicates.in(Arrays.asList(1)))));
assertEvalsToFalse(nasty);
Predicate<? super Integer> stillNasty = SerializableTester.reserializeAndAssert(nasty);
assertEvalsToFalse(stillNasty);
}
// enum singleton pattern
private enum TrimStringFunction implements Function<String, String> {
INSTANCE;
@Override
public String apply(String string) {
return whitespace().trimFrom(string);
}
}
public void testCompose() {
Function<String, String> trim = TrimStringFunction.INSTANCE;
Predicate<String> equalsFoo = Predicates.equalTo("Foo");
Predicate<String> equalsBar = Predicates.equalTo("Bar");
Predicate<String> trimEqualsFoo = Predicates.compose(equalsFoo, trim);
Function<String, String> identity = Functions.identity();
assertTrue(trimEqualsFoo.apply("Foo"));
assertTrue(trimEqualsFoo.apply(" Foo "));
assertFalse(trimEqualsFoo.apply("Foo-b-que"));
new EqualsTester()
.addEqualityGroup(trimEqualsFoo, Predicates.compose(equalsFoo, trim))
.addEqualityGroup(equalsFoo)
.addEqualityGroup(trim)
.addEqualityGroup(Predicates.compose(equalsFoo, identity))
.addEqualityGroup(Predicates.compose(equalsBar, trim))
.testEquals();
}
@GwtIncompatible // SerializableTester
public void testComposeSerialization() {
Function<String, String> trim = TrimStringFunction.INSTANCE;
Predicate<String> equalsFoo = Predicates.equalTo("Foo");
Predicate<String> trimEqualsFoo = Predicates.compose(equalsFoo, trim);
SerializableTester.reserializeAndAssert(trimEqualsFoo);
}
/**
* Tests for Predicates.contains(Pattern) and .containsPattern(String). We assume the regex level
* works, so there are only trivial tests of that aspect. TODO: Fix comment style once annotation
* stripper is fixed.
*/
@GwtIncompatible // Predicates.containsPattern
public void testContainsPattern_apply() {
Predicate<CharSequence> isFoobar = Predicates.containsPattern("^Fo.*o.*bar$");
assertTrue(isFoobar.apply("Foxyzoabcbar"));
assertFalse(isFoobar.apply("Foobarx"));
}
@GwtIncompatible // Predicates.containsPattern
public void testContains_apply() {
Predicate<CharSequence> isFoobar = Predicates.contains(Pattern.compile("^Fo.*o.*bar$"));
assertTrue(isFoobar.apply("Foxyzoabcbar"));
assertFalse(isFoobar.apply("Foobarx"));
}
@GwtIncompatible // NullPointerTester
public void testContainsPattern_nulls() throws Exception {
NullPointerTester tester = new NullPointerTester();
Predicate<CharSequence> isWooString = Predicates.containsPattern("Woo");
tester.testAllPublicInstanceMethods(isWooString);
}
@GwtIncompatible // NullPointerTester
public void testContains_nulls() throws Exception {
NullPointerTester tester = new NullPointerTester();
Predicate<CharSequence> isWooPattern = Predicates.contains(Pattern.compile("Woo"));
tester.testAllPublicInstanceMethods(isWooPattern);
}
@GwtIncompatible // SerializableTester
public void testContainsPattern_serialization() {
Predicate<CharSequence> pre = Predicates.containsPattern("foo");
Predicate<CharSequence> post = SerializableTester.reserializeAndAssert(pre);
assertEquals(pre.apply("foo"), post.apply("foo"));
}
@GwtIncompatible // java.util.regex.Pattern
public void testContains_equals() {
new EqualsTester()
.addEqualityGroup(
Predicates.contains(Pattern.compile("foo")), Predicates.containsPattern("foo"))
.addEqualityGroup(Predicates.contains(Pattern.compile("foo", Pattern.CASE_INSENSITIVE)))
.addEqualityGroup(Predicates.containsPattern("bar"))
.testEquals();
}
public void assertEqualHashCode(
Predicate<? super Integer> expected, Predicate<? super Integer> actual) {
assertEquals(actual + " should hash like " + expected, expected.hashCode(), actual.hashCode());
}
public void testHashCodeForBooleanOperations() {
Predicate<Integer> p1 = Predicates.isNull();
Predicate<Integer> p2 = isOdd();
// Make sure that hash codes are not computed per-instance.
assertEqualHashCode(Predicates.not(p1), Predicates.not(p1));
assertEqualHashCode(Predicates.and(p1, p2), Predicates.and(p1, p2));
assertEqualHashCode(Predicates.or(p1, p2), Predicates.or(p1, p2));
// While not a contractual requirement, we'd like the hash codes for ands
// & ors of the same predicates to not collide.
assertTrue(Predicates.and(p1, p2).hashCode() != Predicates.or(p1, p2).hashCode());
}
@GwtIncompatible // reflection
public void testNulls() throws Exception {
new ClassSanityTester().forAllPublicStaticMethods(Predicates.class).testNulls();
}
@GwtIncompatible // reflection
public void testEqualsAndSerializable() throws Exception {
new ClassSanityTester().forAllPublicStaticMethods(Predicates.class).testEqualsAndSerializable();
}
private static void assertEvalsToTrue(Predicate<? super Integer> predicate) {
assertTrue(predicate.apply(0));
assertTrue(predicate.apply(1));
assertTrue(predicate.apply(null));
}
private static void assertEvalsToFalse(Predicate<? super Integer> predicate) {
assertFalse(predicate.apply(0));
assertFalse(predicate.apply(1));
assertFalse(predicate.apply(null));
}
private static void assertEvalsLikeOdd(Predicate<? super Integer> predicate) {
assertEvalsLike(isOdd(), predicate);
}
private static void assertEvalsLike(
Predicate<? super Integer> expected, Predicate<? super Integer> actual) {
assertEvalsLike(expected, actual, 0);
assertEvalsLike(expected, actual, 1);
assertEvalsLike(expected, actual, null);
}
private static <T> void assertEvalsLike(
Predicate<? super T> expected, Predicate<? super T> actual, T input) {
Boolean expectedResult = null;
RuntimeException expectedRuntimeException = null;
try {
expectedResult = expected.apply(input);
} catch (RuntimeException e) {
expectedRuntimeException = e;
}
Boolean actualResult = null;
RuntimeException actualRuntimeException = null;
try {
actualResult = actual.apply(input);
} catch (RuntimeException e) {
actualRuntimeException = e;
}
assertEquals(expectedResult, actualResult);
if (expectedRuntimeException != null) {
assertNotNull(actualRuntimeException);
assertEquals(expectedRuntimeException.getClass(), actualRuntimeException.getClass());
}
}
@GwtIncompatible // SerializableTester
private static void checkSerialization(Predicate<? super Integer> predicate) {
Predicate<? super Integer> reserialized = SerializableTester.reserializeAndAssert(predicate);
assertEvalsLike(predicate, reserialized);
}
}
7.3Equivalence
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Equivalence;
import com.google.common.base.Equivalence.Wrapper;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.testing.EqualsTester;
import com.google.common.testing.EquivalenceTester;
import com.google.common.testing.NullPointerTester;
import com.google.common.testing.SerializableTester;
import junit.framework.TestCase;
public class EquivalenceTest extends TestCase {
@SuppressWarnings("unchecked") // varargs
public void testPairwiseEquivalent() {
EquivalenceTester.of(Equivalence.equals().<String>pairwise())
.addEquivalenceGroup(ImmutableList.<String>of())
.addEquivalenceGroup(ImmutableList.of("a"))
.addEquivalenceGroup(ImmutableList.of("b"))
.addEquivalenceGroup(ImmutableList.of("a", "b"), ImmutableList.of("a", "b"))
.test();
}
public void testPairwiseEquivalent_equals() {
new EqualsTester()
.addEqualityGroup(Equivalence.equals().pairwise(), Equivalence.equals().pairwise())
.addEqualityGroup(Equivalence.identity().pairwise())
.testEquals();
}
private enum LengthFunction implements Function<String, Integer> {
INSTANCE;
@Override
public Integer apply(String input) {
return input.length();
}
}
private static final Equivalence<String> LENGTH_EQUIVALENCE =
Equivalence.equals().onResultOf(LengthFunction.INSTANCE);
public void testWrap() {
new EqualsTester()
.addEqualityGroup(
LENGTH_EQUIVALENCE.wrap("hello"),
LENGTH_EQUIVALENCE.wrap("hello"),
LENGTH_EQUIVALENCE.wrap("world"))
.addEqualityGroup(LENGTH_EQUIVALENCE.wrap("hi"), LENGTH_EQUIVALENCE.wrap("yo"))
.addEqualityGroup(LENGTH_EQUIVALENCE.wrap(null), LENGTH_EQUIVALENCE.wrap(null))
.addEqualityGroup(Equivalence.equals().wrap("hello"))
.addEqualityGroup(Equivalence.equals().wrap(null))
.testEquals();
}
public void testWrap_get() {
String test = "test";
Wrapper<String> wrapper = LENGTH_EQUIVALENCE.wrap(test);
assertSame(test, wrapper.get());
}
@GwtIncompatible // SerializableTester
public void testSerialization() {
SerializableTester.reserializeAndAssert(LENGTH_EQUIVALENCE.wrap("hello"));
SerializableTester.reserializeAndAssert(Equivalence.equals());
SerializableTester.reserializeAndAssert(Equivalence.identity());
}
private static class IntValue {
private final int value;
IntValue(int value) {
this.value = value;
}
@Override
public String toString() {
return "value = " + value;
}
}
public void testOnResultOf() {
EquivalenceTester.of(Equivalence.equals().onResultOf(Functions.toStringFunction()))
.addEquivalenceGroup(new IntValue(1), new IntValue(1))
.addEquivalenceGroup(new IntValue(2))
.test();
}
public void testOnResultOf_equals() {
new EqualsTester()
.addEqualityGroup(
Equivalence.identity().onResultOf(Functions.toStringFunction()),
Equivalence.identity().onResultOf(Functions.toStringFunction()))
.addEqualityGroup(Equivalence.equals().onResultOf(Functions.toStringFunction()))
.addEqualityGroup(Equivalence.identity().onResultOf(Functions.identity()))
.testEquals();
}
public void testEquivalentTo() {
Predicate<Object> equalTo1 = Equivalence.equals().equivalentTo("1");
assertTrue(equalTo1.apply("1"));
assertFalse(equalTo1.apply("2"));
assertFalse(equalTo1.apply(null));
Predicate<Object> isNull = Equivalence.equals().equivalentTo(null);
assertFalse(isNull.apply("1"));
assertFalse(isNull.apply("2"));
assertTrue(isNull.apply(null));
new EqualsTester()
.addEqualityGroup(equalTo1, Equivalence.equals().equivalentTo("1"))
.addEqualityGroup(isNull)
.addEqualityGroup(Equivalence.identity().equivalentTo("1"))
.testEquals();
}
public void testEqualsEquivalent() {
EquivalenceTester.of(Equivalence.equals())
.addEquivalenceGroup(new Integer(42), 42)
.addEquivalenceGroup("a")
.test();
}
public void testIdentityEquivalent() {
EquivalenceTester.of(Equivalence.identity())
.addEquivalenceGroup(new Integer(42))
.addEquivalenceGroup(new Integer(42))
.addEquivalenceGroup("a")
.test();
}
public void testEquals() {
new EqualsTester()
.addEqualityGroup(Equivalence.equals(), Equivalence.equals())
.addEqualityGroup(Equivalence.identity(), Equivalence.identity())
.testEquals();
}
@GwtIncompatible // NullPointerTester
public void testNulls() {
new NullPointerTester().testAllPublicStaticMethods(Equivalence.class);
new NullPointerTester().testAllPublicInstanceMethods(Equivalence.equals());
new NullPointerTester().testAllPublicInstanceMethods(Equivalence.identity());
}
}
7.4Converter
import com.google.common.base.Converter;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.primitives.Longs;
import com.google.common.testing.EqualsTester;
import com.google.common.testing.SerializableTester;
import junit.framework.TestCase;
import java.util.Iterator;
import java.util.List;
import static com.google.common.base.Functions.toStringFunction;
public class ConverterTest extends TestCase {
private static final Converter<String, Long> STR_TO_LONG =
new Converter<String, Long>() {
@Override
protected Long doForward(String object) {
return Long.valueOf(object);
}
@Override
protected String doBackward(Long object) {
return String.valueOf(object);
}
@Override
public String toString() {
return "string2long";
}
};
private static final Long LONG_VAL = 12345L;
private static final String STR_VAL = "12345";
private static final ImmutableList<String> STRINGS = ImmutableList.of("123", "456");
private static final ImmutableList<Long> LONGS = ImmutableList.of(123L, 456L);
public void testConverter() {
assertEquals(LONG_VAL, STR_TO_LONG.convert(STR_VAL));
assertEquals(STR_VAL, STR_TO_LONG.reverse().convert(LONG_VAL));
Iterable<Long> convertedValues = STR_TO_LONG.convertAll(STRINGS);
assertEquals(LONGS, ImmutableList.copyOf(convertedValues));
}
public void testConvertAllIsView() {
List<String> mutableList = Lists.newArrayList("789", "123");
Iterable<Long> convertedValues = STR_TO_LONG.convertAll(mutableList);
assertEquals(ImmutableList.of(789L, 123L), ImmutableList.copyOf(convertedValues));
Iterator<Long> iterator = convertedValues.iterator();
iterator.next();
iterator.remove();
assertEquals(ImmutableList.of("123"), mutableList);
}
public void testReverse() {
Converter<Long, String> reverseConverter = STR_TO_LONG.reverse();
assertEquals(STR_VAL, reverseConverter.convert(LONG_VAL));
assertEquals(LONG_VAL, reverseConverter.reverse().convert(STR_VAL));
Iterable<String> convertedValues = reverseConverter.convertAll(LONGS);
assertEquals(STRINGS, ImmutableList.copyOf(convertedValues));
assertSame(STR_TO_LONG, reverseConverter.reverse());
assertEquals("string2long.reverse()", reverseConverter.toString());
new EqualsTester()
.addEqualityGroup(STR_TO_LONG, STR_TO_LONG.reverse().reverse())
.addEqualityGroup(STR_TO_LONG.reverse(), STR_TO_LONG.reverse())
.testEquals();
}
public void testReverseReverse() {
Converter<String, Long> converter = STR_TO_LONG;
assertEquals(converter, converter.reverse().reverse());
}
public void testApply() {
assertEquals(LONG_VAL, STR_TO_LONG.apply(STR_VAL));
}
private static class StringWrapper {
private final String value;
public StringWrapper(String value) {
this.value = value;
}
}
public void testAndThen() {
Converter<StringWrapper, String> first =
new Converter<StringWrapper, String>() {
@Override
protected String doForward(StringWrapper object) {
return object.value;
}
@Override
protected StringWrapper doBackward(String object) {
return new StringWrapper(object);
}
@Override
public String toString() {
return "StringWrapper";
}
};
Converter<StringWrapper, Long> converter = first.andThen(STR_TO_LONG);
assertEquals(LONG_VAL, converter.convert(new StringWrapper(STR_VAL)));
assertEquals(STR_VAL, converter.reverse().convert(LONG_VAL).value);
assertEquals("StringWrapper.andThen(string2long)", converter.toString());
assertEquals(first.andThen(STR_TO_LONG), first.andThen(STR_TO_LONG));
}
public void testIdentityConverter() {
Converter<String, String> stringIdentityConverter = Converter.identity();
assertSame(stringIdentityConverter, stringIdentityConverter.reverse());
assertSame(STR_TO_LONG, stringIdentityConverter.andThen(STR_TO_LONG));
assertSame(STR_VAL, stringIdentityConverter.convert(STR_VAL));
assertSame(STR_VAL, stringIdentityConverter.reverse().convert(STR_VAL));
assertEquals("Converter.identity()", stringIdentityConverter.toString());
assertSame(Converter.identity(), Converter.identity());
}
public void testFrom() {
Function<String, Integer> forward =
new Function<String, Integer>() {
@Override
public Integer apply(String input) {
return Integer.parseInt(input);
}
};
Function<Object, String> backward = toStringFunction();
Converter<String, Number> converter = Converter.<String, Number>from(forward, backward);
assertNull(converter.convert(null));
assertNull(converter.reverse().convert(null));
assertEquals((Integer) 5, converter.convert("5"));
assertEquals("5", converter.reverse().convert(5));
}
public void testSerialization_identity() {
Converter<String, String> identityConverter = Converter.identity();
SerializableTester.reserializeAndAssert(identityConverter);
}
public void testSerialization_reverse() {
Converter<Long, String> reverseConverter = Longs.stringConverter().reverse();
SerializableTester.reserializeAndAssert(reverseConverter);
}
public void testSerialization_andThen() {
Converter<String, Long> converterA = Longs.stringConverter();
Converter<Long, String> reverseConverter = Longs.stringConverter().reverse();
Converter<String, String> composedConverter = converterA.andThen(reverseConverter);
SerializableTester.reserializeAndAssert(composedConverter);
}
public void testSerialization_from() {
Converter<String, String> dumb = Converter.from(toStringFunction(), toStringFunction());
SerializableTester.reserializeAndAssert(dumb);
}
}
7.5Supplier
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.Lists;
import com.google.common.testing.ClassSanityTester;
import com.google.common.testing.EqualsTester;
import junit.framework.TestCase;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import static com.google.common.testing.SerializableTester.reserialize;
import static com.google.common.truth.Truth.assertThat;
public class SuppliersTest extends TestCase {
static class CountingSupplier implements Supplier<Integer> {
int calls = 0;
@Override
public Integer get() {
calls++;
return calls * 10;
}
@Override
public String toString() {
return "CountingSupplier";
}
}
static class ThrowingSupplier implements Supplier<Integer> {
@Override
public Integer get() {
throw new NullPointerException();
}
}
static class SerializableCountingSupplier extends CountingSupplier implements Serializable {
private static final long serialVersionUID = 0L;
}
static class SerializableThrowingSupplier extends ThrowingSupplier implements Serializable {
private static final long serialVersionUID = 0L;
}
static void checkMemoize(CountingSupplier countingSupplier, Supplier<Integer> memoizedSupplier) {
// the underlying supplier hasn't executed yet
assertEquals(0, countingSupplier.calls);
assertEquals(10, (int) memoizedSupplier.get());
// now it has
assertEquals(1, countingSupplier.calls);
assertEquals(10, (int) memoizedSupplier.get());
// it still should only have executed once due to memoization
assertEquals(1, countingSupplier.calls);
}
public void testMemoize() {
memoizeTest(new CountingSupplier());
memoizeTest(new SerializableCountingSupplier());
}
private void memoizeTest(CountingSupplier countingSupplier) {
Supplier<Integer> memoizedSupplier = Suppliers.memoize(countingSupplier);
checkMemoize(countingSupplier, memoizedSupplier);
}
public void testMemoize_redudantly() {
memoize_redudantlyTest(new CountingSupplier());
memoize_redudantlyTest(new SerializableCountingSupplier());
}
private void memoize_redudantlyTest(CountingSupplier countingSupplier) {
Supplier<Integer> memoizedSupplier = Suppliers.memoize(countingSupplier);
assertSame(memoizedSupplier, Suppliers.memoize(memoizedSupplier));
}
public void testMemoizeExceptionThrown() {
memoizeExceptionThrownTest(new ThrowingSupplier());
memoizeExceptionThrownTest(new SerializableThrowingSupplier());
}
private void memoizeExceptionThrownTest(ThrowingSupplier throwingSupplier) {
Supplier<Integer> memoizedSupplier = Suppliers.memoize(throwingSupplier);
// call get() twice to make sure that memoization doesn't interfere
// with throwing the exception
for (int i = 0; i < 2; i++) {
try {
memoizedSupplier.get();
fail("failed to throw NullPointerException");
} catch (NullPointerException e) {
// this is what should happen
}
}
}
@GwtIncompatible // SerializableTester
public void testMemoizeNonSerializable() throws Exception {
CountingSupplier countingSupplier = new CountingSupplier();
Supplier<Integer> memoizedSupplier = Suppliers.memoize(countingSupplier);
assertThat(memoizedSupplier.toString()).isEqualTo("Suppliers.memoize(CountingSupplier)");
checkMemoize(countingSupplier, memoizedSupplier);
// Calls to the original memoized supplier shouldn't affect its copy.
memoizedSupplier.get();
assertThat(memoizedSupplier.toString())
.isEqualTo("Suppliers.memoize(<supplier that returned 10>)");
// Should get an exception when we try to serialize.
try {
reserialize(memoizedSupplier);
fail();
} catch (RuntimeException ex) {
assertThat(ex).hasCauseThat().isInstanceOf(java.io.NotSerializableException.class);
}
}
public void testCompose() {
Supplier<Integer> fiveSupplier =
new Supplier<Integer>() {
@Override
public Integer get() {
return 5;
}
};
Function<Number, Integer> intValueFunction =
new Function<Number, Integer>() {
@Override
public Integer apply(Number x) {
return x.intValue();
}
};
Supplier<Integer> squareSupplier = Suppliers.compose(intValueFunction, fiveSupplier);
assertEquals(Integer.valueOf(5), squareSupplier.get());
}
public void testComposeWithLists() {
Supplier<ArrayList<Integer>> listSupplier =
new Supplier<ArrayList<Integer>>() {
@Override
public ArrayList<Integer> get() {
return Lists.newArrayList(0);
}
};
Function<List<Integer>, List<Integer>> addElementFunction =
new Function<List<Integer>, List<Integer>>() {
@Override
public List<Integer> apply(List<Integer> list) {
ArrayList<Integer> result = Lists.newArrayList(list);
result.add(1);
return result;
}
};
Supplier<List<Integer>> addSupplier = Suppliers.compose(addElementFunction, listSupplier);
List<Integer> result = addSupplier.get();
assertEquals(Integer.valueOf(0), result.get(0));
assertEquals(Integer.valueOf(1), result.get(1));
}
@GwtIncompatible // Thread.sleep
public void testMemoizeWithExpiration() throws InterruptedException {
CountingSupplier countingSupplier = new CountingSupplier();
Supplier<Integer> memoizedSupplier =
Suppliers.memoizeWithExpiration(countingSupplier, 75, TimeUnit.MILLISECONDS);
checkExpiration(countingSupplier, memoizedSupplier);
}
@GwtIncompatible // Thread.sleep
private void checkExpiration(
CountingSupplier countingSupplier, Supplier<Integer> memoizedSupplier)
throws InterruptedException {
// the underlying supplier hasn't executed yet
assertEquals(0, countingSupplier.calls);
assertEquals(10, (int) memoizedSupplier.get());
// now it has
assertEquals(1, countingSupplier.calls);
assertEquals(10, (int) memoizedSupplier.get());
// it still should only have executed once due to memoization
assertEquals(1, countingSupplier.calls);
Thread.sleep(150);
assertEquals(20, (int) memoizedSupplier.get());
// old value expired
assertEquals(2, countingSupplier.calls);
assertEquals(20, (int) memoizedSupplier.get());
// it still should only have executed twice due to memoization
assertEquals(2, countingSupplier.calls);
}
public void testOfInstanceSuppliesSameInstance() {
Object toBeSupplied = new Object();
Supplier<Object> objectSupplier = Suppliers.ofInstance(toBeSupplied);
assertSame(toBeSupplied, objectSupplier.get());
assertSame(toBeSupplied, objectSupplier.get()); // idempotent
}
public void testOfInstanceSuppliesNull() {
Supplier<Integer> nullSupplier = Suppliers.ofInstance(null);
assertNull(nullSupplier.get());
}
@GwtIncompatible // Thread
public void testExpiringMemoizedSupplierThreadSafe() throws Throwable {
Function<Supplier<Boolean>, Supplier<Boolean>> memoizer =
new Function<Supplier<Boolean>, Supplier<Boolean>>() {
@Override
public Supplier<Boolean> apply(Supplier<Boolean> supplier) {
return Suppliers.memoizeWithExpiration(supplier, Long.MAX_VALUE, TimeUnit.NANOSECONDS);
}
};
testSupplierThreadSafe(memoizer);
}
@GwtIncompatible // Thread
public void testMemoizedSupplierThreadSafe() throws Throwable {
Function<Supplier<Boolean>, Supplier<Boolean>> memoizer =
new Function<Supplier<Boolean>, Supplier<Boolean>>() {
@Override
public Supplier<Boolean> apply(Supplier<Boolean> supplier) {
return Suppliers.memoize(supplier);
}
};
testSupplierThreadSafe(memoizer);
}
@GwtIncompatible // Thread
public void testSupplierThreadSafe(Function<Supplier<Boolean>, Supplier<Boolean>> memoizer)
throws Throwable {
final AtomicInteger count = new AtomicInteger(0);
final AtomicReference<Throwable> thrown = new AtomicReference<>(null);
final int numThreads = 3;
final Thread[] threads = new Thread[numThreads];
final long timeout = TimeUnit.SECONDS.toNanos(60);
final Supplier<Boolean> supplier =
new Supplier<Boolean>() {
boolean isWaiting(Thread thread) {
switch (thread.getState()) {
case BLOCKED:
case WAITING:
case TIMED_WAITING:
return true;
default:
return false;
}
}
int waitingThreads() {
int waitingThreads = 0;
for (Thread thread : threads) {
if (isWaiting(thread)) {
waitingThreads++;
}
}
return waitingThreads;
}
@Override
public Boolean get() {
// Check that this method is called exactly once, by the first
// thread to synchronize.
long t0 = System.nanoTime();
while (waitingThreads() != numThreads - 1) {
if (System.nanoTime() - t0 > timeout) {
thrown.set(
new TimeoutException(
"timed out waiting for other threads to block"
+ " synchronizing on supplier"));
break;
}
Thread.yield();
}
count.getAndIncrement();
return Boolean.TRUE;
}
};
final Supplier<Boolean> memoizedSupplier = memoizer.apply(supplier);
for (int i = 0; i < numThreads; i++) {
threads[i] =
new Thread() {
@Override
public void run() {
assertSame(Boolean.TRUE, memoizedSupplier.get());
}
};
}
for (Thread t : threads) {
t.start();
}
for (Thread t : threads) {
t.join();
}
if (thrown.get() != null) {
throw thrown.get();
}
assertEquals(1, count.get());
}
@GwtIncompatible // Thread
public void testSynchronizedSupplierThreadSafe() throws InterruptedException {
final Supplier<Integer> nonThreadSafe =
new Supplier<Integer>() {
int counter = 0;
@Override
public Integer get() {
int nextValue = counter + 1;
Thread.yield();
counter = nextValue;
return counter;
}
};
final int numThreads = 10;
final int iterations = 1000;
Thread[] threads = new Thread[numThreads];
for (int i = 0; i < numThreads; i++) {
threads[i] =
new Thread() {
@Override
public void run() {
for (int j = 0; j < iterations; j++) {
Suppliers.synchronizedSupplier(nonThreadSafe).get();
}
}
};
}
for (Thread t : threads) {
t.start();
}
for (Thread t : threads) {
t.join();
}
assertEquals(numThreads * iterations + 1, (int) nonThreadSafe.get());
}
public void testSupplierFunction() {
Supplier<Integer> supplier = Suppliers.ofInstance(14);
Function<Supplier<Integer>, Integer> supplierFunction = Suppliers.supplierFunction();
assertEquals(14, (int) supplierFunction.apply(supplier));
}
@GwtIncompatible // SerializationTester
public void testSerialization() {
assertEquals(Integer.valueOf(5), reserialize(Suppliers.ofInstance(5)).get());
assertEquals(
Integer.valueOf(5),
reserialize(Suppliers.compose(Functions.identity(), Suppliers.ofInstance(5))).get());
assertEquals(Integer.valueOf(5), reserialize(Suppliers.memoize(Suppliers.ofInstance(5))).get());
assertEquals(
Integer.valueOf(5),
reserialize(Suppliers.memoizeWithExpiration(Suppliers.ofInstance(5), 30, TimeUnit.SECONDS))
.get());
assertEquals(
Integer.valueOf(5),
reserialize(Suppliers.synchronizedSupplier(Suppliers.ofInstance(5))).get());
}
@GwtIncompatible // reflection
public void testSuppliersNullChecks() throws Exception {
new ClassSanityTester().forAllPublicStaticMethods(Suppliers.class).testNulls();
}
@GwtIncompatible // reflection
public void testSuppliersSerializable() throws Exception {
new ClassSanityTester().forAllPublicStaticMethods(Suppliers.class).testSerializable();
}
public void testOfInstance_equals() {
new EqualsTester()
.addEqualityGroup(Suppliers.ofInstance("foo"), Suppliers.ofInstance("foo"))
.addEqualityGroup(Suppliers.ofInstance("bar"))
.testEquals();
}
public void testCompose_equals() {
new EqualsTester()
.addEqualityGroup(
Suppliers.compose(Functions.constant(1), Suppliers.ofInstance("foo")),
Suppliers.compose(Functions.constant(1), Suppliers.ofInstance("foo")))
.addEqualityGroup(Suppliers.compose(Functions.constant(2), Suppliers.ofInstance("foo")))
.addEqualityGroup(Suppliers.compose(Functions.constant(1), Suppliers.ofInstance("bar")))
.testEquals();
}
}