List<Person> personList = Lists.newArrayList(person1,person2,person3,person4);
List<List<Person>> subList = Lists.partition(personList,2);
Set<String> s1 = Sets.newHashSet("1","2","3");
Set<String> s2 = Sets.newHashSet("2","3","4");
Sets.difference(s1,s2); //Would return [1]
Sets.difference(s2,s1); //Would return [4]
Sets.symmetricDifference(s1,s2);// Would return [1,4]
Sets.intersection(s1,s2);//Would return [2,3]
Sets.union(s1,s2);//Would return [1,2,3,4]
//常规写法
List<Book> books = someService.getBooks();
Map<String,Book> bookMap = new HashMap<String,Book>()
for(Book book : books){
bookMap.put(book.getIsbn(),book);
}
//guava写法
List<Book> books = someService.getBooks();
Map<String,Book>bookMap = Maps.uniqueIndex(books.iterator(),new Function<Book, String>(){
@Override
public String apply( Book input) {
return input.getIsbn();
}
};)
一个Key关联多个value
ArrayListMultimap是一个使用ArrayList存储一个给定key对应的values。可以通过以下方法来创建一个ArrayListMultimap实例:
ArrayListMultimap<String,String> multiMap = ArrayListMultimap.create();
ArrayListMutilmap<String,String> multiMap = ArrayListMultimap.create(numExcpectedKeys,numExpectedValuesPerKey);
ArrayListMulitmap<String,String> mulitMap = ArrayListMultimap.create(listMultiMap);
需要注意ArrayListMultimap.size计算的是所有values累加起来的值,而不是key集合的大小。
ArrayListMultimap不是一个真正的map对象。如果需要执行map接口的方法。可以先执行asMap方法转换成Map。
Map<String,Collection<String>> map = multiMap.asMap();
HashMultimap是基于hash 实现。与ArrayListMultimap不同, HashMultimap不支持多次插入相同的key-value键值对。
HashMultimap<String,String> multiMap = HashMultimap.create();
multiMap.put("Bar","1");
multiMap.put("Bar","2");
multiMap.put("Bar","3");
multiMap.put("Bar","3");
multiMap.put("Bar","3");
//上面的multiMap.size大小为3而不是5.
不但可以通过key找到对应的value,反过来也可以通过value找到对应的key。为了满足这种操作。map中的value也必须是唯一的。
BiMap<String,String> biMap = HashBiMap.create();
biMap.put("1","Tom");
//This call causes an IllegalArgumentException to be thrown!
biMap.put("2","Tom");
BiMap.forcePut
为了添加相同的value对应不同的key。可以调用forcePut
@Test
public void testBiMapForcePut() throws Exception {
BiMap<String,String> biMap = HashBiMap.create();
biMap.put("1","Tom");
biMap.forcePut("2","Tom");
assertThat(biMap.containsKey("1"),is(false));
assertThat(biMap.containsKey("2"),is(true));
}
BiMap.inverse
@Test
public void testBiMapInverse() throws Exception {
BiMap<String,String> biMap = HashBiMap.create();
biMap.put("1","Tom");
biMap.put("2","Harry");
assertThat(biMap.get("1"),is("Tom"));
assertThat(biMap.get("2"),is("Harry"));
BiMap<String,String> inverseMap = biMap.inverse();
assertThat(inverseMap.get("Tom"),is("1"));
assertThat(inverseMap.get("Harry"),is("2"));
}
可看作 a map of maps
A table is a collection that takes two keys, a row, and a column, and maps those keys to a single value.
HashBasedTable<Integer,Integer,String> table = HashBasedTable.create();
//Creating table with 5 rows and columns initially
HashBasedTable<Integer,Integer,String> table = HashBasedTable.create(5,5);
//Creating a table from an existing table
HashBasedTable<Integer,Integer,String> table = HashBasedTable.create(anotherTable);
Map<Integer,String> columnMap = table.column(1);
Map<Integer,String> rowMap = table.row(2);
The maps returned are live views and change to columnMap and rowMap, or the original table would be reflected in the other. There are other implementations of the table we should discuss briefly as follows:
Range类允许我们使用定义的端点创建特定的时间间隔或值范围,并使用可比较类型。
Range<Integer> numberRange = Range.closed(1,10);
//both return true meaning inclusive
numberRange.contains(10);
numberRange.contains(1);
Range<Integer> numberRange = Range.open(1,10);
//both return false meaning exclusive
numberRange.contains(10);
numberRange.contains(1);
Range类实现了Predicate接口
Since Range objects work with any object that implements the Comparable interface, it makes it easy to create a filter for working with only those objects that fall within our desired boundaries. For example, consider the Person class we introduced before:
public class Person implements Comparable<Person> {
private String firstName;
private String lastName;
private int age;
private String sex;
@Override
public int compareTo(Person o) {
return ComparisonChain.start().
compare(this.firstName,o.getFirstName()).
compare(this.lastName,o.getLastName()).
compare(this.age,o.getAge()).
compare(this.sex,o.getSex()).result();
}
}
We would like to create a Range instance for the Person objects where the age is between 35 and 50. But if you look at the compareTo method, we have a slight problem; it includes all the fields in the object. To solve this problem, we are going to leverage the fact that the Range object implements the Predicate interface. Additionally, we are going to use the Predicates.compose method to create a new Predicate composed of Range and Function. First, let’s define our Range instance:
Range<Integer> ageRange = Range.closed(35,50);
Next, we will create Function that accepts a Person object and returns the age:
Function<Person,Integer> ageFunction = new Function<Person,Integer>() {
@Override
public Integer apply(Person person) {
return person.getAge();
}
};
Finally, we create our composed Predicate:
Predicate<Person> predicate = Predicates.compose(ageRange,ageFunction);
Now we could have just as easily created a Predicate instance to validate an age range. But by using composition, we can substitute either a new Range object or a new Comparable object. The Range object presents an opportunity to perform powerful operations and make other tasks, for example, filtering, more concise.
针对前面提到的每一种集合类型,Guava中都提供了相应的不可变集合版本。
Create immutable collection instances
可变和不可变集合在功能方面没有什么不同。我们这里只讲述一下生成这两者实例间的不同。不可变集合通过Builder模式来构造实例。所有的Guava immutable collections都有一个静态嵌套的Builder类,通过fluent interface approach来创建实例。
MultiMap<Integer,String> map = new ImmutableListMultimap.Builder<Integer,String>()
.put(1,"Foo")
.putAll(2,"Foo","Bar","Baz")
.putAll(4,"Huey","Duey","Luey")
.put(3,"Single").build();
public abstract class Ordering implements Comparator
集合排序在编程中是一个很重要的话题。 鉴于好的集合抽象对编程至关重要,良好的排序工具亦如此。 Ordering类为我们提供了有力和简洁地应用不同排序技术所需的工具。 Ordering是一个抽象类。 尽管它实现了Comparator接口,但Ordering将compare方法声明为abstract。
有两种方式创建Ordering实例
下面是一个根据城市人口数量排序的Comparator。
public class CityByPopluation implements Comparator<City>{
@Override
public int compare(City city1, City city2) {
return Ints.compare(city1.getPopulation(),city2.getPopulation());
}
}
我们通过Ordering和给出的CityByPopluation可以很方便的完成从小到大和从大到小的排序。
//从小到大的排序实例
Ordering.from(cityByPopluation);
//从大到小的排序实例
Ordering.from(cityByPopluation).reverse();
如果集合中存在元素为null,那么该把它们放在前面还是后面。
Ordering.from(comparator).nullsFirst();
在上面的代码中,我们将null视为最小值并放在排序好集合的最前面。相对应的方法是Ordering.nullsLast()
。
通常在对对象进行排序时,我们需要处理sorting criterion相等的情况,并定义a secondary sorting criterion来处理。 之前我们定义了Comparator按人口排序City对象,现在我们有另一个Comparator:
public class CityByRainfall implements Comparator<City> {
@Override
public int compare(City city1, City city2) {
return Doubles.compare(city1.getAverageRainfall(),city2.getAverageRainfall());
}
}
上面给出的Comparator是按照城市的降雨量排序。
Ordering.from(cityByPopulation).compound(cityByRainfall);
上面构造了一个先按照城市人口排序,如果人口相等在按照降雨量排序的Ordering实例。下面是一个使用该Ordering实例的例子
@Test
public void testSecondarySort(){
City city1 = cityBuilder.population(100000).averageRainfall(55.0).build();
City city2 = cityBuilder.population(100000).averageRainfall(45.0).build();
City city3 = cityBuilder.population(100000).averageRainfall(33.8).build();
List<City> cities = Lists.newArrayList(city1,city2,city3);
Ordering<City> secondaryOrdering = Ordering.from(cityByPopulation).compound(cityByRainfall);
Collections.sort(cities,secondaryOrdering);
assertThat(cities.get(0),is(city3));
}
Ordering<City> ordering = Ordering.from(cityByPopluation);
//The Ordering.greatestOf method will return the n greatest elements (five greatest elements in this case).
List<City> topFive = ordering.greatestOf(cityList,5);
//returning the n least elements
List<City> bottomThree = ordering.leastOf(cityList,3);
//集合的最大元素
City maxBottom = ordering.max(cityList);
//集合的最小元素
City maxBottom = ordering.min(cityList);