Guava: Working with Collections II

1. Table

2. ImmutableCollections

3. Comparision Chain & Range

4. Ordering

 

1. Table: Map<R, Map<C, V>>

    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() {
	HashBasedTable<Integer, Integer, String> table = 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<Integer, Integer, String> 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.
Map<Integer, String> columnMap = table.column(columnNo);
Map<Integer, String> 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() {
	Table<Integer, Integer, String> table = 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<Integer, String> rowMap = table.row(0);
	rowMap.put(3, "F"); // table is updated
	assertEquals("F", table.row(0).get(3));

	Map<Integer, String> 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<Integer, Integer, String> immutableTable = ImmutableTable
		.<Integer, Integer, String> 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() {
	List<String> list = Lists.newArrayList("A", "B", "C", "D", "E");

	List<String> addedList = ImmutableList.<String> builder().addAll(list)
		.add("F").build();
	assertEquals(Lists.newArrayList("A", "B", "C", "D", "E", "F"),
		addedList);

	addedList = new ImmutableList.Builder<String>().addAll(list).add("G")
		.build();
	assertEquals(Lists.newArrayList("A", "B", "C", "D", "E", "G"),
		addedList);
    }

    We can see in source code that ImmutableXXX.<T>builder() == new ImmutableXXX.Builder<T>();

  public static <E> Builder<E> builder() {
    return new Builder<E>();
  }

    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.


        2> Usage:

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() {
	Set<Person> persons = 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<Person> {
	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() {
	Range<Person> personRange = 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<Person> {
	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() {
	Range<Person> personRange1 = Range.closed(new Person("A", 1),
		new Person("C", 1));

	Range<Person> personRange2 = Range.closed(new Person("D", 1),
		new Person("F", 2));

	Predicate<Person> 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 {
    List<String> versionList;
    List<String> 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<String> sortedVersionList = Ordering
		.from(new Comparator<String>() {
		    @Override
		    public int compare(String o1, String o2) {
			Function<String, Integer> parseIntFunc = new Function<String, Integer>() {
			    @Override
			    public Integer apply(String input) {
				return Integer.parseInt(input);
			    }
			};
			List<Integer> prevVersions = FluentIterable
				.from(Splitter.on('-').trimResults()
					.omitEmptyStrings().split(o1))
				.transform(parseIntFunc).toList();
			List<Integer> 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<Person> personList = Lists.newArrayList(new Person("Yang", "Male",
		1), new Person("Li", "Female", 2), new Person("Zhang", "Male",
		24), new Person("Yang", "Female", 20));

	List<Person> sortedPersonList = Ordering.from(new Comparator<Person>() {
	    @Override
	    public int compare(Person o1, Person o2) {
		return o1.name.compareTo(o2.name);
	    }
	}).compound(new Comparator<Person>() {
	    @Override
	    public int compare(Person o1, Person o2) {
		return o1.age - o2.age;
	    }
	}).compound(new Comparator<Person>() {
	    @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 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值