1. Table
2. ImmutableCollections
3. Comparision Chain & Range
4. Ordering
1. Table: Map
1> Create table
package edu.xmu.guava.collection; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Test; import com.google.common.collect.HashBasedTable; public class TableTest { @Test public void createTest() { HashBasedTabletable = HashBasedTable .create(); table.put(0, 0, "A"); table.put(0, 1, "B"); table.put(0, 2, "C"); table.put(1, 0, "D"); table.put(1, 1, "E"); assertTrue(table.contains(0, 0)); assertTrue(table.contains(1, 1)); assertFalse(table.contains(1, 2)); assertFalse(table.contains(2, 0)); table = HashBasedTable.create(2, 2); table.put(0, 0, "A"); table.put(0, 1, "B"); table.put(0, 2, "C"); // Will auto expand to ensure capacity table.put(1, 0, "D"); table.put(1, 1, "E"); HashBasedTable table2 = HashBasedTable .create(table); assertEquals(2, table2.rowMap().size()); // total 2 rows assertEquals(3, table2.row(0).size()); // total 3 cols in row 0 assertEquals(3, table2.columnMap().size()); // total 3 cols assertEquals(1, table2.column(2).size()); // total 1 row in col 2 table2.remove(0, 2); assertEquals(2, table2.rowMap().size()); // total 2 rows assertEquals(2, table2.row(0).size()); // total 3 cols in row 0 assertEquals(2, table2.columnMap().size()); // total 2 cols assertEquals(2, table2.column(1).size()); // total 2 rows in col 1 } }
This is the graph representation of the table created above.
2> Table Views: The table provides some great methods for obtaining different views of the underlying data in the table.MapcolumnMap = table.column(columnNo); Map rowMap = table.row(rowNo);
package edu.xmu.guava.collection; import static org.junit.Assert.assertEquals; import java.util.Map; import org.junit.Test; import com.google.common.collect.HashBasedTable; import com.google.common.collect.ImmutableTable; import com.google.common.collect.Table; public class TableTest { @Test(expected = UnsupportedOperationException.class) public void tableViewTest() { Tabletable = HashBasedTable.create(); table.put(0, 0, "A"); table.put(0, 1, "B"); table.put(0, 2, "C"); table.put(1, 0, "D"); table.put(1, 1, "E"); assertEquals("C", table.row(0).get(2)); assertEquals("D", table.row(1).get(0)); assertEquals("E", table.row(1).get(1)); Map rowMap = table.row(0); rowMap.put(3, "F"); // table is updated assertEquals("F", table.row(0).get(3)); Map colMap = table.column(2); colMap.put(3, "G"); // table is updated assertEquals("G", table.row(3).get(2)); assertEquals("G", table.column(2).get(3)); Table immutableTable = ImmutableTable . builder().putAll(table).build(); rowMap = immutableTable.row(0); rowMap.put(4, "H"); // UnsupporttedOperationException will be thrown } }
2. ImmutableCollections
1) If we don't explicitly have a need for a mutable collection, we should always favor using an immutable one.
First of all, immutable collections are completely thread-safe.
Secondly, they offer protection from unknown users who may try to access your code.
@Test public void test() { Listlist = Lists.newArrayList("A", "B", "C", "D", "E"); List addedList = ImmutableList. builder().addAll(list) .add("F").build(); assertEquals(Lists.newArrayList("A", "B", "C", "D", "E", "F"), addedList); addedList = new ImmutableList.Builder ().addAll(list).add("G") .build(); assertEquals(Lists.newArrayList("A", "B", "C", "D", "E", "G"), addedList); }
We can see in source code that ImmutableXXX.
public staticBuilder builder() { return new Builder (); }
Builder pattern is used to create an ImmutableXXX instance.
3. ComparisonChain & Range
1) ComparisionChain:
1> UML for ComparisionChain: Attention that they are using Chain of Responsibity design pattern here.
package edu.xmu.guava.collection; import java.util.Set; import org.apache.log4j.Logger; import org.junit.Test; import com.google.common.collect.ComparisonChain; import com.google.common.collect.Lists; import com.google.common.collect.Sets; public class ComparisionChainTest { Logger logger = Logger.getLogger(ComparisionChainTest.class); @Test public void sortTest() { Setpersons = Sets.newTreeSet(Lists.newArrayList(new Person( "Yang", 23), new Person("Yang", 20), new Person("Yang", 33), new Person("Li", 12), new Person("Zhang", 21))); logger.info(persons); } static class Person implements Comparable { private String name; private int age; public Person(String name, int age) { super(); this.name = name; this.age = age; } public int compareTo(Person o) { return ComparisonChain.start().compare(this.name, o.name) .compare(this.age, o.age).result(); } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } } }
2) Range:
1> It is usually used with ComparisionChain and serve as/for Predicate
2> Range object implements the Predicate interface
@Test public void comparableTest() { RangepersonRange = Range.closed(new Person("A", 1), new Person("B", 21)); assertTrue(personRange.contains(new Person("A", 2))); assertTrue(personRange.contains(new Person("A", 21))); assertTrue(personRange.contains(new Person("A", Integer.MAX_VALUE))); assertTrue(personRange.contains(new Person("B", 1))); assertTrue(personRange.contains(new Person("B", 21))); assertFalse(personRange.contains(new Person("B", 22))); } public static class Person implements Comparable { private String name; private int age; public Person(String name, int age) { super(); this.name = name; this.age = age; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } @Override public int compareTo(Person o) { return ComparisonChain.start().compare(this.name, o.name) .compare(this.age, o.age).result(); } }
@Test public void comparableTest2() { RangepersonRange1 = Range.closed(new Person("A", 1), new Person("C", 1)); Range personRange2 = Range.closed(new Person("D", 1), new Person("F", 2)); Predicate personPredicate = Predicates.or(personRange1, personRange2); assertTrue(personPredicate.apply(new Person("B", 1))); assertTrue(personPredicate.apply(new Person("C", 1))); assertTrue(personPredicate.apply(new Person("D", Integer.MAX_VALUE))); assertTrue(personPredicate.apply(new Person("E", 1))); assertTrue(personPredicate.apply(new Person("E", Integer.MAX_VALUE))); assertFalse(personPredicate.apply(new Person("F", 3))); }
4. Ordering:
package edu.xmu.guava.collections; import static org.junit.Assert.assertEquals; import java.util.Comparator; import java.util.List; import org.junit.Before; import org.junit.Test; import com.google.common.base.Function; import com.google.common.base.Splitter; import com.google.common.collect.ComparisonChain; import com.google.common.collect.FluentIterable; import com.google.common.collect.Lists; import com.google.common.collect.Ordering; public class OrderingTest { ListversionList; List descSortedVersionList; @Before public void setUp() { versionList = Lists.newArrayList("11-0", "1-1", "2-1", "11-21", "11-111", "0-1"); descSortedVersionList = Lists.newArrayList("11-111", "11-21", "11-0", "2-1", "1-1", "0-1"); } @Test public void sortTest() { List sortedVersionList = Ordering .from(new Comparator () { @Override public int compare(String o1, String o2) { Function parseIntFunc = new Function () { @Override public Integer apply(String input) { return Integer.parseInt(input); } }; List prevVersions = FluentIterable .from(Splitter.on('-').trimResults() .omitEmptyStrings().split(o1)) .transform(parseIntFunc).toList(); List currVersions = FluentIterable .from(Splitter.on('-').trimResults() .omitEmptyStrings().split(o2)) .transform(parseIntFunc).toList(); return ComparisonChain .start() .compare(prevVersions.get(0), currVersions.get(0)) .compare(prevVersions.get(1), currVersions.get(1)).result(); } }).reverse().sortedCopy(versionList); assertEquals(descSortedVersionList, sortedVersionList); } @Test public void sortTest2() { List personList = Lists.newArrayList(new Person("Yang", "Male", 1), new Person("Li", "Female", 2), new Person("Zhang", "Male", 24), new Person("Yang", "Female", 20)); List sortedPersonList = Ordering.from(new Comparator () { @Override public int compare(Person o1, Person o2) { return o1.name.compareTo(o2.name); } }).compound(new Comparator () { @Override public int compare(Person o1, Person o2) { return o1.age - o2.age; } }).compound(new Comparator () { @Override public int compare(Person o1, Person o2) { return o1.gender.compareTo(o2.gender); } }).sortedCopy(personList); System.out.println(sortedPersonList); } public class Person { private String name; private String gender; private int age; public Person(String name, String gender, int age) { super(); this.name = name; this.gender = gender; this.age = age; } @Override public String toString() { return "Person [name=" + name + ", gender=" + gender + ", age=" + age + "]"; } } }
Comments: We can use Ordering without changing the Person (no need to implements Comparable).
Reference Links:
1) Getting Started with Google Guava -Bill Bejeck