Knowledge Transfer

Ethickfox kb page with all notes


Project maintained by ethickfox Hosted on GitHub Pages — Theme by mattgraham

==Guava== - open-source set of libraries for Java, developed by Google Engineers. It provides utility methods for collections (old and new), caching, primitive support, concurrency, common annotations, string processing, I/O and validations.

Collections

Guava provides new Collection types:

https://github.com/google/guava/wiki/NewCollectionTypesExplained

==Table==

Map with two keys. Works as replacement for cases like Map<FirstName, Map<LastName, Person>>

Table<Vertex, Vertex, Double> weightedGraph = HashBasedTable.create();
weightedGraph.put(v1, v2, 4);
weightedGraph.put(v1, v3, 20);
weightedGraph.put(v2, v3, 5);

weightedGraph.row(v1); // returns a Map mapping v2 to 4, v3 to 20
weightedGraph.column(v3); // returns a Map mapping v1 to 20, v2 to 5

Implementations:

Table<String, String, Double> weightedGraph = HashBasedTable.create();
weightedGraph.put("v1", "v2", 4.0);
weightedGraph.put("v1", "v3", 20.0);
weightedGraph.put("v2", "v3", 5.0);

Result:

		v1  v2  v3
v1      4.0 20.0
v2          5.0
v3

Consists of backingMap and rowMap

Untitled 55.png

==BiMap==

Map that

BiMap.put(key, value) will throw an IllegalArgumentExceptionif you attempt to map a key to an already-present value. If you wish to delete any preexisting entry with the specified value, use BiMap.forcePut(key, value)instead.

Implementations:

Key-Value Map Impl Value-Key Map Impl Corresponding BiMap
HashMap HashMap HashBiMap
ImmutableMap ImmutableMap ImmutableBiMap
EnumMap EnumMap EnumBiMap
EnumMap HashMap EnumHashBiMap

==Multimap==

Map that allows to associate keys with arbitrarily many values.

a -> [1, 2, 4]
b -> [3]
c -> [5]

Usage:

// creates a ListMultimap with tree keys and array list values
ListMultimap<String, Integer> treeListMultimap =
    MultimapBuilder.treeKeys().arrayListValues().build();

// creates a SetMultimap with hash keys and enum set values
SetMultimap<Integer, MyEnum> hashEnumMultimap =
    MultimapBuilder.hashKeys().enumSetValues(MyEnum.class).build();

Multimap.get(key) returns a view of the values associated with the specified key, even if there are none currently.

Set<Person> aliceChildren = childrenMultimap.get(alice);
aliceChildren.clear();
aliceChildren.add(bob);
aliceChildren.add(carol);

writes through to the underlying multimap.
Other ways of modifying the multimap (more directly) include:

Signature Description Equivalent
put(K, V) Adds an association from the key to the value. multimap.get(key).add(value)
putAll(K, Iterable<V>) Adds associations from the key to each of the values in turn. Iterables.addAll(multimap.get(key), values)
remove(K, V) Removes one association from key to value and returns true if the multimap changed. multimap.get(key).remove(value)
removeAll(K) Removes and returns all the values associated with the specified key. The returned collection may or may not be modifiable, but modifying it will not affect the multimap. (Returns the appropriate collection type.) multimap.get(key).clear()
replaceValues(K, Iterable<V>) Clears all the values associated with key and sets key to be associated with each of values. Returns the values that were previously associated with the key. multimap.get(key).clear(); Iterables.addAll(multimap.get(key), values)

Multimap also supports a number of powerful views. Such as asMap, entries, keySet, keys, values

Implementations:

Implementation Keys behave like... Values behave like..
ArrayListMultimap HashMap ArrayList
HashMultimap HashMap HashSet
LinkedListMultimap LinkedHashMap LinkedList
LinkedHashMultimap LinkedHashMap LinkedHashSet
TreeMultimap TreeMap TreeSet
ImmutableListMultimap ImmutableMap ImmutableList
ImmutableSetMultimap ImmutableMap ImmutableSet

If you need more customization, use Multimaps.newMultimap(Map, Supplier<Collection>)or the list and set versions to use a custom collection, list, or set implementation to back your multimap.

==Multiset==

Set that allows us to store values in multiple instances. It might be treated as:

As an advantage it have method count(Object) returns the count associated with that element.

Method Description
count(E) Count the number of occurrences of an element that have been added to this multiset.
elementSet() View the distinct elements of a Multiset<E> as a Set<E>.
entrySet() Similar to Map.entrySet(), returns a Set<Multiset.Entry<E>>, containing entries supporting getElement() and getCount().
add(E, int) Adds the specified number of occurrences of the specified element.
remove(E, int) Removes the specified number of occurrences of the specified element.
setCount(E, int) Sets the occurrence count of the specified element to the specified nonnegative value.
size() Returns the total number of occurrences of all elements in the Multiset.

Note thatMultiset<E> is not a Map<E, Integer>, though that might be part of a Multiset implementation. Multiset is a true Collection type, and satisfies all of the associated contractual obligations.

Implementations:

Map Corresponding Multiset Supports null elements
HashMap HashMultiset Yes
TreeMap TreeMultiset Yes
LinkedHashMap LinkedHashMultiset Yes
ConcurrentHashMap ConcurrentHashMultiset No
ImmutableMap ImmutableMultiset No

==ClassToInstanceMap==

Map with classes as key values.

In addition to extending the Map interface, ClassToInstanceMap provides the methods T getInstance(Class<T>) and T putInstance(Class<T>, T) , which eliminate the need for unpleasant casting while enforcing type safety.

==RangeSet==

RangeSet describes a set of disconnected, nonempty ranges. When adding a range to a mutable RangeSet, any connected ranges are merged together, and empty ranges are ignored. For example:

RangeSet<Integer> rangeSet = TreeRangeSet.create();
rangeSet.add(Range.closed(1, 10)); // {[1, 10]}
rangeSet.add(Range.closedOpen(11, 15)); // disconnected range: {[1, 10], [11, 15)}
rangeSet.add(Range.closedOpen(15, 20)); // connected range; {[1, 10], [11, 20)}
rangeSet.add(Range.openClosed(0, 0)); // empty range; {[1, 10], [11, 20)}
rangeSet.remove(Range.open(5, 10)); // splits [1, 10]; {[1, 5], [10, 10], [11, 20)}

RangeSet implementations support an extremely wide range of views, including:

In addition to operations on its views, RangeSet supports several query operations directly, the most prominent of which are:

==RangeMap==

RangeMap is a collection type describing a mapping from disjoint, nonempty ranges to values. Unlike RangeSetRangeMapnever "coalesces" adjacent mappings, even if adjacent ranges are mapped to the same values.

RangeMap<Integer, String> rangeMap = TreeRangeMap.create();
rangeMap.put(Range.closed(1, 10), "foo"); // {[1, 10] => "foo"}
rangeMap.put(Range.open(3, 6), "bar"); // {[1, 3] => "foo", (3, 6) => "bar", [6, 10] => "foo"}
rangeMap.put(Range.open(10, 20), "foo"); // {[1, 3] => "foo", (3, 6) => "bar", [6, 10] => "foo", (10, 20) => "foo"}
rangeMap.remove(Range.closed(5, 11)); // {[1, 3] => "foo", (3, 5) => "bar", (11, 20) => "foo"}

==BloomFilter==

Bloom filters are a probabilistic data structure, allowing you to test if an object is definitely not in the filter, or was probably added to the Bloom filter. The Wikipedia page is fairly comprehensive, and we recommend this tutorial.

BloomFilter<Person> friends = BloomFilter.create(personFunnel, 500, 0.01);
for (Person friend : friendsList) {
  friends.put(friend);
}
// much later
if (friends.mightContain(someone)) {
  // the probability that someone reached this place if they aren't a friend is
  // 1% we might, for example, start asynchronously loading things for someone
  // while we do a more expensive exact check
}

==Utils, for collection creating:==

public static final ImmutableSet<Color> GOOGLE_COLORS =
   ImmutableSet.<Color>builder()
       .addAll(WEBSAFE_COLORS)
       .add(new Color(0, 191, 255))
       .build();

Caching

Guava provides a wide ==caching functionality==, you can add rule via CacheLoader and after that, use CacheBuilder with loader. Also note that we're using the getUnchecked() operation, which computes and loads the value into the cache if it doesn't already exist. Moreover, we can add some restrictions (time, size, e.g) and manage or cache.

@Test
public void whenEntryIdle_thenEviction() throws InterruptedException {
	CacheLoader<String, String> loader;
	loader = new CacheLoader<String, String>() {

	@Override
	public String load(String key) {
		return key.toUpperCase();
	}
};

	LoadingCache<String, String> cache;
	cache = CacheBuilder.newBuilder().build(loader);
	
	assertEquals(0, cache.size());
	assertEquals("HELLO", cache.getUnchecked("hello"));
	assertEquals(1, cache.size());
}

Concurrency

Math

Math provides us a few classes with special mathematical operations:

@Test
public void whenFactorialInt_shouldReturnTheResultIfInIntRange() {
    int result = IntMath.factorial(5);
 
    assertEquals(120, result);
}

I/O

Guava provides special classes to simplify work with files:

@Test
public void whenReadMultipleLinesUsingFiles_thenRead() throws IOException {
    File file = new File("test.txt");
    List<String> result = Files.readLines(file, Charsets.UTF_8);

    assertThat(result, contains("John", "Jane", "Adam", "Tom"));
}

Another examples:

Data

==EventBus== allows to publish-subscribe communication between components. Subscribers register via special annotations. When some event called, EventBus finds subscribers capable of receiving this type of event and notifies them of the event.

public class EventListener {
	private static int eventsHandled;

	@Subscribe
	public void stringEvent(String event) {
		eventsHandled++;
	}
}

EventBus eventBus = new EventBus();
EventListener listener = new EventListener();

eventBus.register(listener);
eventBus.post("String Event");
eventBus.unregister(listener);

Reflection

Guava provides simplest way proxy creation:

Java CoreFoo foo = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), 
new Class<?>[] {Foo.class}, 
invocationHandler);

Foo foo = Reflection.newProxy(Foo.class, invocationHandler)

TypeToken - Allows to identify generic class type in runtime, to deal with type erasure.

TypeToken<List<String>> stringListToken = new TypeToken<List<String>>() {};

Invokable - wrapper of java.lang.reflect.Method and java.lang.reflect.Constructor. It provides a simpler API on top of a standard Java reflection API

Method method = CustomClass.class.getMethod("somePublicMethod"); //reflection api
Invokable<CustomClass, ?> invokable = new TypeToken<CustomClass>() {}
	.method(method);//guava api

boolean isPublicStandradJava = Modifier.isPublic(method.getModifiers());
boolean isPublicGuava = invokable.isPublic();

Utilities

Useful classes that reduces boilerplate code

Objects

Existed before java.util.Objects, have equal and hashCode methods which are deprecated since Java 7, because of appearance of java.util.Objects.

MoreObjects

Have toStringHelper method which allows to create to custom values toString for debug purposes

// Returns "MyObject{x=1}"
   MoreObjects.toStringHelper("MyObject")
       .add("x", 1)
       .toString();

ComparasionChain

Performs lazy comparation in non verbose way

public int compareTo(Foo that) {
     return ComparisonChain.start()
         .compare(this.aString, that.aString)
         .compare(this.anInt, that.anInt)
         .compare(this.anEnum, that.anEnum, Ordering.natural().nullsLast())
         .result();
   }

Stopwatch

Class for time measurement

   Stopwatch stopwatch = Stopwatch.createStarted();
   doSomething();
   stopwatch.stop(); // optional

   long millis = stopwatch.elapsed(MILLISECONDS);

   log.info("time: " + stopwatch); // formatted string like "12.3 ms"

Joiner and Splitter

Allows to convert collection into a string with Joiner and string to collection with Splitter

List<String> names = Lists.newArrayList("John", "Jane", "Adam", "Tom");
String result = Joiner.on(",").join(names);

// "John,Jane,Adam,Tom"

Map<String, Integer> salary = Maps.newHashMap();
salary.put("John", 1000);
salary.put("Jane", 1500);
String result = Joiner.on(" , ").withKeyValueSeparator(" = ")
                                    .join(salary);
//"John = 1000" , "Jane = 1500"
String input = "John=first,Adam=second";
Map<String, String> result = Splitter.on(",")
                                         .withKeyValueSeparator("=")
                                         .split(input);
result.get("John"); // first
result.get("Adam"); // second

Preconditions

This class provides a list of static methods for checking that a method or a constructor is invoked with valid parameter values. If a precondition fails, a tailored exception is thrown.

Preconditions.checkArgument(age>10, "message");
Preconditions.checkElementIndex(6, numbers.length - 1, message);
Preconditions.checkNotNull(nullObject, message);
Preconditions.checkState(Arrays.binarySearch(validStates, givenState) > 0, message);

CharMatcher

Offers basic text processing methods

String input = "H*el.lo,}12日本人中";
CharMatcher matcher = CharMatcher.ascii();
String result = matcher.removeFrom(input); // 日本人中
result = matcher.retainFrom(input); // H*el.lo,}12

Ordering

Set of configurable ordering definitions for collections

Collections.sort(toSort, Ordering.natural().nullsFirst());
Collections.sort(toSort, Ordering.natural().reverse());
Ordering<String> byLength = new OrderingByLenght();
Ordering.natural().isStrictlyOrdered(sorted) // check of collection is sorted

ClassPath

Scans the source of a ClassLoader and finds all loadable classes and resources

Hashing

Utility class for hashing

String sha256hex = Hashing.sha256()
  .hashString(originalString, StandardCharsets.UTF_8)
  .toString();