Guava-Java核心工具库(一)

guava

最近在公司的项目中注意到了一个依赖guava,在项目中很多地方都用到了它,特别是集合转换时大量使用,而Guava的通用性和实用性相信每一个javaer都有所体会,今天就来介绍一下这款来自Google的Java核心工具库。

官方是这样介绍Guava

Guava is a set of core Java libraries from Google that includes new collection types (such as multimap and multiset), immutable collections, a graph library, and utilities for concurrency, I/O, hashing, primitives, strings, and more! It is widely used on most Java projects within Google, and widely used by many other companies as well.

翻译过来就是,Guava 是 Google 的一组核心 Java 库,其中包括新的集合类型(例如 multimap 和 multiset)、不可变集合、图形库以及用于并发、I/O、哈希、原语、字符串等的实用程序!它被广泛用于 Google 内部的大多数 Java 项目,也被许多其他公司广泛使用。

使用

<dependency>
  <groupId>com.google.guava</groupId>
  <artifactId>guava</artifactId>
  <version>33.3.0-jre</version>
  <!-- or, for Android: -->
  <version>33.3.0-android</version>
</dependency>

Collections(集合)

Immutable collections

public static final ImmutableSet<String> COLOR_NAMES = ImmutableSet.of(
  "red",
  "orange",
  "yellow",
  "green",
  "blue",
  "purple");

class Foo {
  final ImmutableSet<Bar> bars;
  Foo(Set<Bar> bars) {
    this.bars = ImmutableSet.copyOf(bars); // defensive copy!
  }
}
  1. 可以被不受信任的库安全使用
  2. 可以在多线程间没有竞争条件风险的使用
  3. 可以用作常数,并期望它保持不变。
    在这里插入图片描述

New collection types

Guava 引入了许多 JDK 中没有的新集合类型,结果发现它们非常有用。这些都是为了与 JDK 集合框架愉快地共存而设计的,而不是将某些东西硬塞到 JDK 集合抽象中。

Multiset(多集)

统计一个单词在文本中出现了多少次是这样的

Map<String, Integer> counts = new HashMap<String, Integer>();
for (String word : words) {
  Integer count = counts.get(word);
  if (count == null) {
    counts.put(word, 1);
  } else {
    counts.put(word, count + 1);
  }
}

multiset.add(word)就能解决上述问题

Multimap

结果类似于Map<K, List> 或 Map<K, Set>。例如,Map<K, Set> 是表示无标签有向图的典型方式。 Guava 的 Multimap 框架可以轻松处理从键到多个值的映射。多重映射是将键与任意多个值关联起来的通用方法。

// 创建一个按键排序的Multimap
Multimap<String, Integer> treeMultimap = MultimapBuilder.treeKeys().hashSetValues().build();

// 创建一个使用哈希表存储键的Multimap
Multimap<String, Integer> hashMultimap = MultimapBuilder.hashKeys().arrayListValues().build();
Bimap

将值映射回键的传统方法是维护两个单独的映射并使它们保持同步,但这很容易出现错误,并且当值已存在于映射中时可能会变得非常混乱。

Map<String, Integer> nameToId = Maps.newHashMap();
Map<Integer, String> idToName = Maps.newHashMap();

nameToId.put("Bob", 42);
idToName.put(42, "Bob");
// what happens if "Bob" or 42 are already present?
// weird bugs can arise if we forget to keep these in sync...

BiMap<K, V>

允许您使用 inverse() 查看反映射BiMap<V, K>

确保值是唯一的,使values()成为一个Set

如果您尝试将键映射到已经存在的值,BiMap.put(key, value) 将抛出 IllegalArgumentException。如果您希望删除具有指定值的任何预先存在的条目,请改用 BiMap.forcePut(key, value)

BiMap<String, Integer> userId = HashBiMap.create();
...

String userForId = userId.inverse().get(id);

New collection出了上面三个常用的类型外,还有Table、ClassToInstanceMap、RangeSet、RangeMap,这些在 [github](GitHub - google/guava: Google core libraries for Java) 上有详细介绍和用法示例

Extension utilities

Forwarding Decorators(转发装饰器)

对于所有各种集合接口,Guava 提供了 Forwarding 抽象类来简化装饰器模式的使用。

class AddLoggingList<E> extends ForwardingList<E> {
  final List<E> delegate; // backing list
  @Override protected List<E> delegate() {
    return delegate;
  }
  @Override public void add(int index, E elem) {
    log(index, elem);
    super.add(index, elem);
  }
  @Override public boolean add(E elem) {
    return standardAdd(elem); // implements in terms of add(int, E)
  }
  @Override public boolean addAll(Collection<? extends E> c) {
    return standardAddAll(c); // implements in terms of add
  }
}
PeekingIterator

Iterators 支持 Iterators.peekingIterator(Iterator) 方法,该方法包装 Iterator 并返回 PeekingIterator,它是 Iterator 的子类型,可让您 peek() 查找下一次调用 next() 将返回的元素。

List<E> result = Lists.newArrayList();
PeekingIterator<E> iter = Iterators.peekingIterator(source.iterator());
while (iter.hasNext()) {
  E current = iter.next();
  while (iter.hasNext() && iter.peek().equals(current)) {
    // skip this duplicate element
    iter.next();
  }
  result.add(current);
}

Graphs

  1. Definitions

    graph.addEdge(nodeU, nodeV, edgeUV);
    
    • nodeU和nodeV是互相邻近的
    • edgeUV关联nodeU和nodeV,反之亦然

    如果是有向图

    • nodeU是nodeV的前者
    • nodeV是nodeU的后者
    • edgeUV是nodeU的出边
    • edgeUV是nodeV的入边
    • nodeU是edgeUV的源头
    • nodeV是edgeUV的终点

    如果是无向图

    • nodeU是nodeV的前者和后者
    • nodeV是nodeU的前者和后者
    • edgeUV是nodeU的入边和出边
    • edgeUV是nodeV的入边和出边
Graph

Graph是最简单、最基本的图类型。它定义了处理节点到节点关系的低级运算符,例如 successors(node)、adjacentNodes(node) 和 inDegree(node)。它的节点是一级唯一对象;您可以将它们视为类似于将键映射到图形内部数据结构中

在这里插入图片描述

ValueGraph

ValueGraph是带权重的Graph
在这里插入图片描述

Network

Network 具有 Graph 所具有的所有与节点相关的方法,但添加了处理边和节点到边关系的方法,例如 outEdges(node)、incidentNodes(edge) 和 EdgesConnecting(nodeU, nodeV)。
在这里插入图片描述

构建图实例
// Creating mutable graphs
MutableGraph<Integer> graph = GraphBuilder.undirected().build();

MutableValueGraph<City, Distance> roads = ValueGraphBuilder.directed()
    .incidentEdgeOrder(ElementOrder.stable())
    .build();

MutableNetwork<Webpage, Link> webSnapshot = NetworkBuilder.directed()
    .allowsParallelEdges(true)
    .nodeOrder(ElementOrder.natural())
    .expectedNodeCount(100000)
    .expectedEdgeCount(1000000)
    .build();

// Creating an immutable graph
ImmutableGraph<Country> countryAdjacencyGraph =
    GraphBuilder.undirected()
        .<Country>immutable()
        .putEdge(FRANCE, GERMANY)
        .putEdge(FRANCE, BELGIUM)
        .putEdge(GERMANY, BELGIUM)
        .addNode(ICELAND)
        .build();
图的遍历
Iterable<Path> iterable =
    Traverser.<Path>forTree(
            // This lambda function implements SuccessorsFunction, which returns the
            // successor nodes of a given node.
            path -> path.isDirectory() ? path.listFiles() : ImmutableList.of())
        .breadthFirst(Path.ROOT);

stream(iterable).filter(path -> containsText(path, query)).findFirst();

还有可变图和不可变图等等,Guava里的图对象和数学概念相对应,这些概念和应用在我们大多数项目中极少用到,不必太过深究,确实碰到了,我们也可以查阅 [github](GitHub - google/guava: Google core libraries for Java) 上Guava工程师写的文档,进一步了解Graph的使用。

  • 30
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雨路行人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值