知识点
相关文章
更多最近更新
更多Guava学习笔记:Guava新集合-Table等
2019-03-08 21:48|来源: 网络
Table
当我们需要多个索引的数据结构的时候,通常情况下,我们只能用这种丑陋的Map<FirstName, Map<LastName, Person>>来实现。为此Guava提供了一个新的集合类型-Table集合类型,来支持这种数据结构的使用场景。Table支持“row”和“column”,而且提供多种视图。
@Test public void TableTest(){ Table<String, Integer, String> aTable = HashBasedTable.create(); for (char a = 'A'; a <= 'C'; ++a) { for (Integer b = 1; b <= 3; ++b) { aTable.put(Character.toString(a), b, String.format("%c%d", a, b)); } } System.out.println(aTable.column(2)); System.out.println(aTable.row("B")); System.out.println(aTable.get("B", 2)); System.out.println(aTable.contains("D", 1)); System.out.println(aTable.containsColumn(3)); System.out.println(aTable.containsRow("C")); System.out.println(aTable.columnMap()); System.out.println(aTable.rowMap()); System.out.println(aTable.remove("B", 3)); }
输出:
{A=A2, B=B2, C=C2} {1=B1, 2=B2, 3=B3} B2 false true true {1={A=A1, B=B1, C=C1}, 2={A=A2, B=B2, C=C2}, 3={A=A3, B=B3, C=C3}} {A={1=A1, 2=A2, 3=A3}, B={1=B1, 2=B2, 3=B3}, C={1=C1, 2=C2, 3=C3}} B3
Table视图:
rowMap()返回一个Map<R, Map<C, V>>的视图。rowKeySet()类似地返回一个Set<R>。
row(r)返回一个非null的Map<C, V>。修改这个视图Map也会导致原表格的修改。
和列相关的方法有columnMap(), columnKeySet()和column(c)。(基于列的操作会比基于行的操作效率差些)
cellSet()返回的是以Table.Cell<R, C, V>为元素的Set。这里的Cell就类似Map.Entry,但是它是通过行和列来区分的。
Table有以下实现:
HashBasedTable:基于HashMap<R, HashMap<C, V>>的实现。
TreeBasedTable:基于TreeMap<R, TreeMap<C, V>>的实现。
ImmutableTable:基于ImmutableMap<R, ImmutableMap<C, V>>的实现。(注意,ImmutableTable已对稀疏和密集集合做了优化)
ArrayTable:ArrayTable是一个需要在构建的时候就需要定下行列的表格。这种表格由二维数组实现,这样可以在密集数据的表格的场合,提高时间和空间的效率。
ClassToInstanceMap
有的时候,你的map的key并不是一种类型,他们是很多类型,你想通过映射他们得到这种类型,guava提供了ClassToInstanceMap满足了这个目的。
除了继承自Map接口,ClassToInstaceMap提供了方法 T getInstance(Class<T>) 和 T putInstance(Class<T>, T),消除了强制类型转换。
该类有一个简单类型的参数,通常称为B,代表了map控制的上层绑定,例如:
ClassToInstanceMap<Number> numberDefaults = MutableClassToInstanceMap.create(); numberDefaults.putInstance(Integer.class, Integer.valueOf(0));
从技术上来说,ClassToInstanceMap<B> 实现了Map<Class<? extends B>, B>,或者说,这是一个从B的子类到B对象的映射,这可能使得ClassToInstanceMap的泛型轻度混乱,但是只要记住B总是Map的上层绑定类型,通常来说B只是一个对象。
guava提供了有用的实现, MutableClassToInstanceMap 和 ImmutableClassToInstanceMap.
重点:像其他的Map<Class,Object>,ClassToInstanceMap 含有的原生类型的项目,一个原生类型和他的相应的包装类可以映射到不同的值;
import org.junit.Test; import com.google.common.collect.ClassToInstanceMap; import com.google.common.collect.HashBasedTable; import com.google.common.collect.MutableClassToInstanceMap;
public class OtherTest { @Test public void ClassToInstanceMapTest() { ClassToInstanceMap<String> classToInstanceMapString =MutableClassToInstanceMap.create(); ClassToInstanceMap<Person> classToInstanceMap =MutableClassToInstanceMap.create(); Person person= new Person("peida",20); System.out.println("person name :"+person.name+" age:"+person.age); classToInstanceMapString.put(String.class, "peida"); System.out.println("string:"+classToInstanceMapString.getInstance(String.class)); classToInstanceMap.putInstance(Person.class,person); Person person1=classToInstanceMap.getInstance(Person.class); System.out.println("person1 name :"+person1.name+" age:"+person1.age); } } class Person { public String name; public int age; Person(String name, int age) { this.name = name; this.age = age; } }
RangeSet
RangeSet用来处理一系列不连续,非空的range。当添加一个range到一个RangeSet之后,任何有连续的range将被自动合并,而空的range将被自动去除。例如:
@Test public void RangeSetTest(){ RangeSet<Integer> rangeSet = TreeRangeSet.create(); rangeSet.add(Range.closed(1, 10)); System.out.println("rangeSet:"+rangeSet); rangeSet.add(Range.closedOpen(11, 15)); System.out.println("rangeSet:"+rangeSet); rangeSet.add(Range.open(15, 20)); System.out.println("rangeSet:"+rangeSet); rangeSet.add(Range.openClosed(0, 0)); System.out.println("rangeSet:"+rangeSet); rangeSet.remove(Range.open(5, 10)); System.out.println("rangeSet:"+rangeSet); }
输出: rangeSet:{[1‥10]} rangeSet:{[1‥10][11‥15)} rangeSet:{[1‥10][11‥15)(15‥20)} rangeSet:{[1‥10][11‥15)(15‥20)} rangeSet:{[1‥5][10‥10][11‥15)(15‥20)}
注意,像合并Range.closed(1, 10)和Range.closedOpen(11, 15)这样的情况,我们必须先用调用Range.canonical(DiscreteDomain)传入DiscreteDomain.integers()处理一下。
RangeSet的视图
RangeSet的实现支持了十分丰富的视图,包括:
complement():是个辅助的RangeSet,它本身就是一个RangeSet,因为它包含了非连续,非空的range。
subRangeSet(Range<C>): 返回的是一个交集的视图。
asRanges():返回可以被迭代的Set<Range<C>>的视图。
asSet(DiscreteDomain<C>) (ImmutableRangeSet only):返回一个ImmutableSortedSet<C>类型的视图,里面的元素是range里面的元素,而不是range本身。(如果DiscreteDomain和RangeSet的上限或下限是无限的话,这个操作就不能支持)
Queries
除了支持各种视图,RangeSet还支持各种直接的查询操作,其中最重要的是:
contains(C):这是RangeSet最基本的操作,它能查询给定的元素是否在RangeSet里。
rangeContaining(C): 返回包含给定的元素的Range,如果不存在就返回null。
encloses(Range<C>): 用来判断给定的Range是否包含在RangeSet里面。
span():返回一个包含在这个RangeSet的所有Range的并集。
RangeMap
RangeMap代表了非连续非空的range对应的集合。不像RangeSet,RangeMap不会合并相邻的映射,甚至相邻的range对应的是相同的值。例如:
@Test public void RangeMapTest(){ RangeMap<Integer, String> rangeMap = TreeRangeMap.create(); rangeMap.put(Range.closed(1, 10), "foo"); System.out.println("rangeMap:"+rangeMap); rangeMap.put(Range.open(3, 6), "bar"); System.out.println("rangeMap:"+rangeMap); rangeMap.put(Range.open(10, 20), "foo"); System.out.println("rangeMap:"+rangeMap); rangeMap.remove(Range.closed(5, 11)); System.out.println("rangeMap:"+rangeMap); } 输出: rangeMap:[[1‥10]=foo] rangeMap:[[1‥3]=foo, (3‥6)=bar, [6‥10]=foo] rangeMap:[[1‥3]=foo, (3‥6)=bar, [6‥10]=foo, (10‥20)=foo] rangeMap:[[1‥3]=foo, (3‥5)=bar, (11‥20)=foo]
RangeMap的视图
RangeMap提供了两种视图:
asMapOfRanges():返回Map<Range<K>, V>类型的视图。这个操作可以被用作迭代操作。
subRangeMap(Range<K>)提供给定Range的交集。这个操作可以推广到传统的headMap, subMap, 和tailMap。
相关问答
更多-
使用Guava ForwardingList装饰集合的意外行为(Unexpected behaviour decorating a collection using Guava ForwardingList)[2022-06-25]
这种模式可行的唯一方法是,在创建装饰器后再也不会再次引用originalList 。 ForwardingList可能无法控制originalList发生的事情。 (没有装饰者可以。) 总的来说,你应该做的是创建一个工厂方法,它返回一个全新的装饰列表,永远不会让你访问原始列表。 The only way this pattern is going to work is if you never reference originalList again after you've created the dec ... -
严重的是,番石榴一切都很有用。 我一直在使用它一段时间,而且我仍然总是发现一些新的东西,它可以减少代码而不是用手做的。 有些事情其他人并没有真正提到我爱: Multimap只是很棒。 任何时候,您都可以使用Map
> ,使用多重图形,并为您自定义一个繁琐的检查映射到一个键的现有集合,如果不存在则创建和添加它。 Ordering对于构建Comparator是非常好的,它们的行为只是你想要的。 Maps.uniqueIndex和Multimaps.index :这些方法采 ... -
从集合中获取属性列表使用Guava获取统一列表(Get list of properties from collection Into unified list using Guava)[2024-01-04]
要将组集合展平为单个组集合,可以使用FluentIterable.transformAndConcat(Function) : public static final Function> GROUP_COLLECTIONS_TO_GROUP_COLLECTION = new Function >() { @Override publ ... -
番石榴表CSV(Guava table to CSV)[2023-03-09]
您将需要使用entrySet()而不是values() ,然后将每个条目映射到其键和值的列表: printer.printRecords(graph.rowMap().entrySet() .stream() .map(entry -> ImmutableList.builder() .add(entry.getKey()) .addAll(entry.getValue().values()) ... -
在JavaFX TableView中显示Google Guava表的规范方式(Canonical way to display Google Guava table in JavaFX TableView)[2023-10-15]
这样做很容易。 只需为columnKeySet()每个值创建一个列,并为columnKeySet()每个值创建一个项: public final class GuavaTableConverter { private GuavaTableConverter() { } public staticList > getColumns(Table table, Function h ... -
是否有针对Guava MultiSet和Table概念的scala替代品?(Is there a scala replacement for Guava MultiSet and Table concepts?)[2023-05-29]
您可以使用Map[(R, C), V]而不是Table和Map[T, Int]而不是Multiset 。 您还可以向Map[T, Int]添加辅助方法Map[T, Int]如下所示: implicit class Multiset[T](val m: Map[T, Int]) extends AnyVal { def setAdd(e: T, i: Int = 1) = { val cnt = m.getOrElse(e, 0) + i if (cnt <= 0) ... -
番石榴贡献者在这里。 不要使用构造函数,请使用HashBasedTable.create()工厂方法。 (没有参数,或与expectedRows和expectedCellsPerRow 。) 使用table.put("A100", "B100", 5) ,就像使用两个键的Map一样。 Guava contributor here. Don't use the constructor, use the HashBasedTable.create() factory method. (With no argum ...
-
Table行为就像一个Map ,即第二个put覆盖了第一个。 你需要的是一种Multimap 。 对于一个已经存在的问题 ,已经有一个问题 ,投票给它。 目前,您可以使用 Table
> 或者a Map , MyBean> 我推荐后者,因为组合键比处理“多”的东西简单得多。 如果你今天感觉很酷,你甚至可以使用 Map 只是不要告诉任何人这是我的 ... -
AbstractScheduledServiced实现Service 。 Service接口描述了生命周期方法,包括startAsync 。 ServiceState枚举文字包含有关其含义的文档。 处于NEW状态的服务(刚刚创建): 处于此状态的服务处于非活动状态。 它做的工作量极少,占用资源极少。 要使服务执行某些有用的操作,您必须将其转换为RUNNING状态 此状态下的服务正在运行。 这就是为什么你必须在它做任何事之前启动服务的原因。 我还建议不要从构造函数中调用startAsync,而是从创建MySe ...
-
如何使用Guava构建ConcurrentLinkedHashmap?(How to build a ConcurrentLinkedHashmap using Guava?)[2022-04-14]
ConcurrentLinkedHashmap API未移植到Guava 1:1,但CLHM的一些解决方案在MapMaker和Cache (使用CacheBuilder )中使用。 ConcurrentLinkedHashmap的作者Ben Manes回答了一个问题,可能会澄清您的疑问: ConcurrentLinkedHashMap已经集成到Guava中意味着什么? : 番石榴是长期替代品,大多数时候你应该使用它。 历史是ConcurrentLinkedHashMap找出算法,Guava包含它,然后专注于 ...