Guava进修笔记:Guava新增凑集类型-Multimap
添加时间:2013-7-9 点击量:
在日常的开辟工作中,我们有的时辰须要机关像Map<K, List<V>>或者Map<K, Set<V>>如许斗劲错杂的凑集类型的数据布局,以便做响应的营业逻辑处理惩罚。例如:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Test;
public class MultimapTest {
Map<String, List<StudentScore>> StudentScoreMap = new HashMap<String, List<StudentScore>>();
@Test
public void testStudentScore(){
for(int i=10;i<20;i++){
StudentScore studentScore=new StudentScore();
studentScore.CourseId=1001+i;
studentScore.score=100-i;
addStudentScore(peida,studentScore);
}
System.out.println(StudentScoreMap:+StudentScoreMap.size());
System.out.println(StudentScoreMap:+StudentScoreMap.containsKey(peida));
System.out.println(StudentScoreMap:+StudentScoreMap.containsKey(jerry));
System.out.println(StudentScoreMap:+StudentScoreMap.size());
System.out.println(StudentScoreMap:+StudentScoreMap.get(peida).size());
List<StudentScore> StudentScoreList=StudentScoreMap.get(peida);
if(StudentScoreList!=null&&StudentScoreList.size()>0){
for(StudentScore stuScore:StudentScoreList){
System.out.println(stuScore one:+stuScore.CourseId+ score:+stuScore.score);
}
}
}
public void addStudentScore(final String stuName,final StudentScore studentScore) {
List<StudentScore> stuScore = StudentScoreMap.get(stuName);
if (stuScore == null) {
stuScore = new ArrayList<StudentScore>();
StudentScoreMap.put(stuName, stuScore);
}
stuScore.add(studentScore);
}
}
class StudentScore{
int CourseId;
int score;
}
申明:想 Map<String, List<StudentScore>> StudentScoreMap = new HashMap<String, List<StudentScore>>()如许的数据布局,本身实现起来太麻烦,你须要搜检key是否存在,不存在时则创建一个,存在时在List后面添加上一个。这个过程是斗劲疾苦的,若是你搜检List中的对象是否存在,删除一个对象,或者遍历全部数据布局,那么则须要更多的代码来实现。
Multimap
Guava的Multimap就供给了一个便利地把一个键对应到多个值的数据布局。让我们可以简单优雅的实现上脸错杂的数据布局,让我们的精力和时候放在实现营业逻辑上,而不是在数据布局上,下面我们具体来看看Multimap的相干常识点。
上方的代码和数据布局用Multimap来实现,代码布局清楚简单了很多吧,具体代码如下:
@Test
public void teststuScoreMultimap(){
Multimap<String,StudentScore> scoreMultimap = ArrayListMultimap.create();
for(int i=10;i<20;i++){
StudentScore studentScore=new StudentScore();
studentScore.CourseId=1001+i;
studentScore.score=100-i;
scoreMultimap.put(peida,studentScore);
}
System.out.println(scoreMultimap:+scoreMultimap.size());
System.out.println(scoreMultimap:+scoreMultimap.keys());
}
调用Multimap.get(key)会返回这个键对应的值的凑集的视图(view),没有对应凑集就返回空凑集。对于ListMultimap来说,这个办返回一个List,对于SetMultimap来说,这个办法就返回一个Set。批改数据是经由过程批改底层Multimap来实现的。例如:
@Test
public void teststuScoreMultimap(){
Multimap<String,StudentScore> scoreMultimap = ArrayListMultimap.create();
for(int i=10;i<20;i++){
StudentScore studentScore=new StudentScore();
studentScore.CourseId=1001+i;
studentScore.score=100-i;
scoreMultimap.put(peida,studentScore);
}
System.out.println(scoreMultimap:+scoreMultimap.size());
System.out.println(scoreMultimap:+scoreMultimap.keys());
Collection<StudentScore> studentScore = scoreMultimap.get(peida);
studentScore.clear();
StudentScore studentScoreNew=new StudentScore();
studentScoreNew.CourseId=1034;
studentScoreNew.score=67;
studentScore.add(studentScoreNew);
System.out.println(scoreMultimap:+scoreMultimap.size());
System.out.println(scoreMultimap:+scoreMultimap.keys());
}
Multimap也支撑一系列强大的视图功能:
1.asMap把自身Multimap<K, V>映射成Map<K, Collection<V>>视图。这个Map视图支撑remove和批改操纵,然则不支撑put和putAll。严格地来讲,当你传入参数是不存在的key,并且你返回的是null而不是一个空的可批改的凑集的时辰就可以调用asMap().get(key)。(你可以强迫转型asMap().get(key)的成果类型-对SetMultimap的成果转成Set,对ListMultimap的成果转成List型-然则直接把ListMultimap转成Map<K, List<V>>是不可的。)
2.entries视图是把Multimap里所有的键值对以Collection<Map.Entry<K, V>>的情势显现。
3.keySet视图是把Multimap的键凑集作为视图
4.keys视图返回的是个Multiset,这个Multiset是以不反复的键对应的个数作为视图。这个Multiset可以经由过程支撑移除操纵而不是添加操纵来批改Multimap。
5.values()视图能把Multimap里的所有值“平坦”成一个Collection<V>。这个操纵和Iterables.concat(multimap.asMap().values())很类似,只是它返回的是一个完全的Collection。
尽管Multimap的实现用到了Map,但Multimap<K, V>不是Map<K, Collection<V>>。因为两者有明显差别:
1.Multimap.get(key)必然返回一个非null的凑集。但这不默示Multimap应用了内存来接洽关系这些键,相反,返回的凑集只是个容许添加元素的视图。
2.若是你喜好像Map那样当不存在键的时辰要返回null,而不是Multimap那样返回空凑集的话,可以用asMap()返回的视图来获得Map<K, Collection<V>>。(这种景象下,你得把返回的Collection<V>强转型为List或Set)。
3.Multimap.containsKey(key)只有在这个键存在的时辰才返回true。
4.Multimap.entries()返回的是Multimap所有的键值对。然则若是须要key-collection的键值对,那就得用asMap().entries()。
5.Multimap.size()返回的是entries的数量,而不是不反复键的数量。若是要获得不反复键的数量就得用Multimap.keySet().size()。
@Test
public void teststuScoreMultimap(){
Multimap<String,StudentScore> scoreMultimap = ArrayListMultimap.create();
for(int i=10;i<20;i++){
StudentScore studentScore=new StudentScore();
studentScore.CourseId=1001+i;
studentScore.score=100-i;
scoreMultimap.put(peida,studentScore);
}
System.out.println(scoreMultimap:+scoreMultimap.size());
System.out.println(scoreMultimap:+scoreMultimap.keys());
Collection<StudentScore> studentScore = scoreMultimap.get(peida);
StudentScore studentScore1=new StudentScore();
studentScore1.CourseId=1034;
studentScore1.score=67;
studentScore.add(studentScore1);
StudentScore studentScore2=new StudentScore();
studentScore2.CourseId=1045;
studentScore2.score=56;
scoreMultimap.put(jerry,studentScore2);
System.out.println(scoreMultimap:+scoreMultimap.size());
System.out.println(scoreMultimap:+scoreMultimap.keys());
for(StudentScore stuScore : scoreMultimap.values()) {
System.out.println(stuScore one:+stuScore.CourseId+ score:+stuScore.score);
}
scoreMultimap.remove(jerry,studentScore2);
System.out.println(scoreMultimap:+scoreMultimap.size());
System.out.println(scoreMultimap:+scoreMultimap.get(jerry));
scoreMultimap.put(harry,studentScore2);
scoreMultimap.removeAll(harry);
System.out.println(scoreMultimap:+scoreMultimap.size());
System.out.println(scoreMultimap:+scoreMultimap.get(harry));
}
Multimap的实现
Multimap供给了雄厚的实现,所以你可以用它来调换法度里的Map<K, Collection<V>>,具体的实现如下:
Implementation Keys 的行动类似 Values的行动类似
ArrayListMultimap HashMap ArrayList
HashMultimap HashMap HashSet
LinkedListMultimap LinkedHashMap LinkedList
LinkedHashMultimap LinkedHashMap LinkedHashSet
TreeMultimap TreeMap TreeSet
ImmutableListMultimap ImmutableMap ImmutableList
ImmutableSetMultimap ImmutableMap ImmutableSet
以上这些实现,除了immutable的实现都支撑null的键和值。
1.LinkedListMultimap.entries()能保持迭代时的次序。
2.LinkedHashMultimap保持插入的次序,以及键的插入次序。
要重视并不是所有的实现都正真实现了Map<K, Collection<V>>!(尤其是有些Multimap的实现为了最小话开销,应用了自定义的hash table)
所有随风而逝的都属于昨天的,所有历经风雨留下来的才是面向未来的。—— 玛格丽特·米切尔 《飘》
在日常的开辟工作中,我们有的时辰须要机关像Map<K, List<V>>或者Map<K, Set<V>>如许斗劲错杂的凑集类型的数据布局,以便做响应的营业逻辑处理惩罚。例如:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Test;
public class MultimapTest {
Map<String, List<StudentScore>> StudentScoreMap = new HashMap<String, List<StudentScore>>();
@Test
public void testStudentScore(){
for(int i=10;i<20;i++){
StudentScore studentScore=new StudentScore();
studentScore.CourseId=1001+i;
studentScore.score=100-i;
addStudentScore(peida,studentScore);
}
System.out.println(StudentScoreMap:+StudentScoreMap.size());
System.out.println(StudentScoreMap:+StudentScoreMap.containsKey(peida));
System.out.println(StudentScoreMap:+StudentScoreMap.containsKey(jerry));
System.out.println(StudentScoreMap:+StudentScoreMap.size());
System.out.println(StudentScoreMap:+StudentScoreMap.get(peida).size());
List<StudentScore> StudentScoreList=StudentScoreMap.get(peida);
if(StudentScoreList!=null&&StudentScoreList.size()>0){
for(StudentScore stuScore:StudentScoreList){
System.out.println(stuScore one:+stuScore.CourseId+ score:+stuScore.score);
}
}
}
public void addStudentScore(final String stuName,final StudentScore studentScore) {
List<StudentScore> stuScore = StudentScoreMap.get(stuName);
if (stuScore == null) {
stuScore = new ArrayList<StudentScore>();
StudentScoreMap.put(stuName, stuScore);
}
stuScore.add(studentScore);
}
}
class StudentScore{
int CourseId;
int score;
}
申明:想 Map<String, List<StudentScore>> StudentScoreMap = new HashMap<String, List<StudentScore>>()如许的数据布局,本身实现起来太麻烦,你须要搜检key是否存在,不存在时则创建一个,存在时在List后面添加上一个。这个过程是斗劲疾苦的,若是你搜检List中的对象是否存在,删除一个对象,或者遍历全部数据布局,那么则须要更多的代码来实现。
Multimap
Guava的Multimap就供给了一个便利地把一个键对应到多个值的数据布局。让我们可以简单优雅的实现上脸错杂的数据布局,让我们的精力和时候放在实现营业逻辑上,而不是在数据布局上,下面我们具体来看看Multimap的相干常识点。
上方的代码和数据布局用Multimap来实现,代码布局清楚简单了很多吧,具体代码如下:
@Test
public void teststuScoreMultimap(){
Multimap<String,StudentScore> scoreMultimap = ArrayListMultimap.create();
for(int i=10;i<20;i++){
StudentScore studentScore=new StudentScore();
studentScore.CourseId=1001+i;
studentScore.score=100-i;
scoreMultimap.put(peida,studentScore);
}
System.out.println(scoreMultimap:+scoreMultimap.size());
System.out.println(scoreMultimap:+scoreMultimap.keys());
}
调用Multimap.get(key)会返回这个键对应的值的凑集的视图(view),没有对应凑集就返回空凑集。对于ListMultimap来说,这个办返回一个List,对于SetMultimap来说,这个办法就返回一个Set。批改数据是经由过程批改底层Multimap来实现的。例如:
@Test
public void teststuScoreMultimap(){
Multimap<String,StudentScore> scoreMultimap = ArrayListMultimap.create();
for(int i=10;i<20;i++){
StudentScore studentScore=new StudentScore();
studentScore.CourseId=1001+i;
studentScore.score=100-i;
scoreMultimap.put(peida,studentScore);
}
System.out.println(scoreMultimap:+scoreMultimap.size());
System.out.println(scoreMultimap:+scoreMultimap.keys());
Collection<StudentScore> studentScore = scoreMultimap.get(peida);
studentScore.clear();
StudentScore studentScoreNew=new StudentScore();
studentScoreNew.CourseId=1034;
studentScoreNew.score=67;
studentScore.add(studentScoreNew);
System.out.println(scoreMultimap:+scoreMultimap.size());
System.out.println(scoreMultimap:+scoreMultimap.keys());
}
Multimap也支撑一系列强大的视图功能:
1.asMap把自身Multimap<K, V>映射成Map<K, Collection<V>>视图。这个Map视图支撑remove和批改操纵,然则不支撑put和putAll。严格地来讲,当你传入参数是不存在的key,并且你返回的是null而不是一个空的可批改的凑集的时辰就可以调用asMap().get(key)。(你可以强迫转型asMap().get(key)的成果类型-对SetMultimap的成果转成Set,对ListMultimap的成果转成List型-然则直接把ListMultimap转成Map<K, List<V>>是不可的。)
2.entries视图是把Multimap里所有的键值对以Collection<Map.Entry<K, V>>的情势显现。
3.keySet视图是把Multimap的键凑集作为视图
4.keys视图返回的是个Multiset,这个Multiset是以不反复的键对应的个数作为视图。这个Multiset可以经由过程支撑移除操纵而不是添加操纵来批改Multimap。
5.values()视图能把Multimap里的所有值“平坦”成一个Collection<V>。这个操纵和Iterables.concat(multimap.asMap().values())很类似,只是它返回的是一个完全的Collection。
尽管Multimap的实现用到了Map,但Multimap<K, V>不是Map<K, Collection<V>>。因为两者有明显差别:
1.Multimap.get(key)必然返回一个非null的凑集。但这不默示Multimap应用了内存来接洽关系这些键,相反,返回的凑集只是个容许添加元素的视图。
2.若是你喜好像Map那样当不存在键的时辰要返回null,而不是Multimap那样返回空凑集的话,可以用asMap()返回的视图来获得Map<K, Collection<V>>。(这种景象下,你得把返回的Collection<V>强转型为List或Set)。
3.Multimap.containsKey(key)只有在这个键存在的时辰才返回true。
4.Multimap.entries()返回的是Multimap所有的键值对。然则若是须要key-collection的键值对,那就得用asMap().entries()。
5.Multimap.size()返回的是entries的数量,而不是不反复键的数量。若是要获得不反复键的数量就得用Multimap.keySet().size()。
@Test
public void teststuScoreMultimap(){
Multimap<String,StudentScore> scoreMultimap = ArrayListMultimap.create();
for(int i=10;i<20;i++){
StudentScore studentScore=new StudentScore();
studentScore.CourseId=1001+i;
studentScore.score=100-i;
scoreMultimap.put(peida,studentScore);
}
System.out.println(scoreMultimap:+scoreMultimap.size());
System.out.println(scoreMultimap:+scoreMultimap.keys());
Collection<StudentScore> studentScore = scoreMultimap.get(peida);
StudentScore studentScore1=new StudentScore();
studentScore1.CourseId=1034;
studentScore1.score=67;
studentScore.add(studentScore1);
StudentScore studentScore2=new StudentScore();
studentScore2.CourseId=1045;
studentScore2.score=56;
scoreMultimap.put(jerry,studentScore2);
System.out.println(scoreMultimap:+scoreMultimap.size());
System.out.println(scoreMultimap:+scoreMultimap.keys());
for(StudentScore stuScore : scoreMultimap.values()) {
System.out.println(stuScore one:+stuScore.CourseId+ score:+stuScore.score);
}
scoreMultimap.remove(jerry,studentScore2);
System.out.println(scoreMultimap:+scoreMultimap.size());
System.out.println(scoreMultimap:+scoreMultimap.get(jerry));
scoreMultimap.put(harry,studentScore2);
scoreMultimap.removeAll(harry);
System.out.println(scoreMultimap:+scoreMultimap.size());
System.out.println(scoreMultimap:+scoreMultimap.get(harry));
}
Multimap的实现
Multimap供给了雄厚的实现,所以你可以用它来调换法度里的Map<K, Collection<V>>,具体的实现如下:
Implementation Keys 的行动类似 Values的行动类似
ArrayListMultimap HashMap ArrayList
HashMultimap HashMap HashSet
LinkedListMultimap LinkedHashMap LinkedList
LinkedHashMultimap LinkedHashMap LinkedHashSet
TreeMultimap TreeMap TreeSet
ImmutableListMultimap ImmutableMap ImmutableList
ImmutableSetMultimap ImmutableMap ImmutableSet
以上这些实现,除了immutable的实现都支撑null的键和值。
1.LinkedListMultimap.entries()能保持迭代时的次序。
2.LinkedHashMultimap保持插入的次序,以及键的插入次序。
要重视并不是所有的实现都正真实现了Map<K, Collection<V>>!(尤其是有些Multimap的实现为了最小话开销,应用了自定义的hash table)