当提供线程安全映射时, Guava的Tables.newCustomTable(Map,Supplier)方法是否会返回线程安全表?例如:
public static <R, C, V> Table<R, C, V> newConcurrentTable() {
return Tables.newCustomTable(
new ConcurrentHashMap<R, Map<C, V>>(),
new Supplier<Map<C, V>>() {
public Map<C, V> get() {
return new ConcurrentHashMap<C, V>();
}
});
}
Run Code Online (Sandbox Code Playgroud)
该代码是否实际返回并发表?
我有一些带有Map<String, Map<String, String>>对象的代码,它有效(它被实例化为HashMaps的HashMap),但我想知道是否有更好的方法来表示Guava中的这个数据结构.
我也考虑过Multimap,但同时有ListMultimap和SetMultimap番石榴,我没有发现任何"MapMultimap".
我也检查过Table,它看起来更像是它,但它的名字让我感到不舒服:我所拥有的绝对不是一张桌子而是一棵树.(第二个键之间没有重叠)
是否有更好的番石榴替代品或我应该坚持使用Map<String, Map<String, String>>?
是否有一种替代Guava Tables,它使用基元而不是泛型类型作为键?
我想使用原语来避免因使用Java Numbers和Java Maps创建的其他入口对象而导致的自动装箱.
我使用Trove TLongObjectMap编译了我自己的基本LongLongObjectTable ,但是如果有可用的话,我更愿意使用标准库.
private static class LongLongObjectTable<T> {
private final TLongObjectMap<TLongObjectMap<T>> backingMap = new TLongObjectHashMap<>();
T get(final long rowKey, final long columnKey) {
final TLongObjectMap<T> map = this.backingMap.get(rowKey);
if (map == null) {
return null;
}
return map.get(columnKey);
}
void put(final long rowKey, final long columnKey, final T value) {
TLongObjectMap<T> map = this.backingMap.get(rowKey);
if (map == null) {
map = new TLongObjectHashMap<>();
this.backingMap.put(rowKey, map);
}
map.put(columnKey, value);
}
Collection<T> values() …Run Code Online (Sandbox Code Playgroud) 我有一个用Java编写的JSON Schema实现,它依赖于Jackson(版本2.1.x).出于准确性原因,我告诉杰克逊使用BigDecimal浮点数.
对于JSON Schema的需求,特别需要:对于数值,JSON值相等由其数学值的相等性定义.我需要这种检查,因为,例如,这不是一个合法的模式(一个enum应该是唯一的值):
{ "enum": [ 1, 1.0 ] }
Run Code Online (Sandbox Code Playgroud)
但对于JsonNodes 1和1.0不相等.因此,我编写了番石榴等效的实现,并Set<Equivalence.Wrapper<JsonNode>>在适当的地方使用.此实现应适用于所有类型的节点,而不仅仅是数字节点.
而这个实现中最困难的部分原来是doHash()数字节点:/我需要相同的哈希码来获得等效的数学值,无论它们是整数还是浮点数.
我现在能想到的最好的是:
@Override
protected int doHash(final JsonNode t)
{
/*
* If this is a numeric node, we want a unique hashcode for all possible
* number nodes.
*/
if (t.isNumber()) {
final BigDecimal decimal = t.decimalValue();
try {
return decimal.toBigIntegerExact().hashCode();
} catch (ArithmeticException ignored) {
return decimal.stripTrailingZeros().hashCode();
}
} …Run Code Online (Sandbox Code Playgroud) 我将首先用我的用例快速激发问题.我的库需要将Java异常分类器暴露给它插入的框架.例如:
enum Classification { FATAL, TRANSIENT, UNKNOWN }
Classification classify(Throwable t) {
if (t instanceof MyTransientException)
return Classification.TRANSIENT;
else if (t instanceof MyFatalException)
return Classification.FATAL;
else
return Classification.UNKNOWN;
}
Run Code Online (Sandbox Code Playgroud)
有时,由于我无法控制的原因,传递的异常是我感兴趣的一个包装器所以我想搜索它的原因链.我最初的想法是:
Classification classify(Throwable t) {
if (t == null)
return Classification.UNKNOWN;
if (t instanceof MyTransientException)
return Classification.TRANSIENT;
else if (t instanceof MyFatalException)
return Classification.FATAL;
else
return classify(t.getCause());
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,如果传递的异常在其因果链中有一个循环,这可能导致无限递归.这样的异常很可能不会被传递,并且如果创建了这样的异常,可能会在系统的其他地方出现错误,但我对我的库负责生产的可能性感到非常不舒服如果发生中断.Throwable的API和javadoc没有明确禁止这种可能性,因为循环在因果链中本质上是无意义的.
我注意到Guava有一个@Beta方法来提取因果链Throwables.getCausalChain,但它的实现容易受到同样的问题 - 它最终会抛出一个OOME.
我打算使用身份哈希集来检测周期并降低风险,但我想听听别人如何看待这个问题.你觉得我过度防守吗?你会怎么做?
在java中,EnumSet使用long(RegularEnumSet)或long[](JumboEnumSet)将它包含的项存储在位掩码/位向量中.我现在遇到了一个用例,我有几千个域对象(让我们称之为Node),每个Flag对象都会按照每个对象不同的顺序显示枚举的所有项(让我们称之为).
目前我将Order存储为Guava ImmutableSet,因为这可以保证保留插入顺序.但是,我使用了本页中介绍的方法来比较a EnumSet<Flag>,an ImmutableSet<Flag>和a 中的内存使用情况Flag[].以下是a)Flag有64个枚举项和b)所有三个变量包含所有64个项的结果:
EnumSet:32字节
ImmutableSet:832字节
数组:272字节
所以我的问题是:是否有一种聪明的方法将枚举排序打包成数值以使内存占用量小于数组的内存占用量?如果它有所不同:在我的用例中,我会假设订购总是包含所有枚举项目.
澄清:我的枚举比这小得多,我现在没有任何记忆问题,这种情况也不会给我带来记忆问题.只是在这种微观层面上,这种低效率会让我感到困惑.
更新:
在得到各种答案和评论的建议之后,我想出了这个使用字节数组的数据结构.警告:它没有实现Set接口(不检查唯一值),并且它不会扩展到超出字节可容纳的大枚举.此外,复杂性非常糟糕,因为必须重复查询Enum.values()(请参阅此处讨论此问题),但这里是:
public class EnumOrdering<E extends Enum<E>> implements Iterable<E> {
private final Class<E> type;
private final byte[] order;
public EnumOrdering(final Class<E> type, final Collection<E> order) {
this.type = type;
this.order = new byte[order.size()];
int offset = 0;
for (final E item : order) {
this.order[offset++] = (byte) …Run Code Online (Sandbox Code Playgroud) 在Guava中,给定了Collection<E>一个我认识e的类型和元素元素E,我想创建一个首先Ordering<E>排序的自定义,e然后是集合的其余部分.然而,到达那里的方式似乎非常复杂:
Collection<String> values = ImmutableList.of("apples", "oranges", "pears");
String first = "oranges";
List<String> remainingValues = newArrayList(values); // this
remainingValues.remove(first); // seems
Ordering<String> myOrdering = // very
Ordering.explicit(first, remainingValues.toArray( // complicated!
new String[remainingValues.size()])); // is there an easier way?
Run Code Online (Sandbox Code Playgroud)
我想要的是这样的事情:
Ordering.explicit(first);
Run Code Online (Sandbox Code Playgroud)
(我希望这可以排序first到开头并保留所有其他元素的顺序,但是文档说生成的Ordering会抛出一个ClassCastException未明确列出的元素.)
或者像这样:
Ordering.explicit(first, values.toArray(/* etc */));
Run Code Online (Sandbox Code Playgroud)
(但这会失败,因为它first会是一个重复的值)
有人能想出一个简洁的方法来做我想做的事吗?
顺便说一句,它不一定是一个Ordering,也可能是Iterable在指定的订单中创建一个变通方法,但同样,这是非常复杂的:
Iterable<String> sorted = Iterables.concat(
ImmutableList.of(first),
Iterables.filter(values, not(equalTo(first))));
Run Code Online (Sandbox Code Playgroud) 我正在使用Guava的EventBus来启动一些处理和报告结果.这是一个非常简单的可编译示例:
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
public class Test {
public static class InitiateProcessing { }
public static class ProcessingStarted { }
public static class ProcessingResults { }
public static class ProcessingFinished { }
public static EventBus bus = new EventBus();
@Subscribe
public void receiveStartRequest(InitiateProcessing evt) {
System.out.println("Got processing request - starting processing");
bus.post(new ProcessingStarted());
System.out.println("Generating results");
bus.post(new ProcessingResults());
System.out.println("Generating more results");
bus.post(new ProcessingResults());
bus.post(new ProcessingFinished());
}
@Subscribe
public void processingStarted(ProcessingStarted evt) {
System.out.println("Processing has started");
}
@Subscribe
public void resultsReceived(ProcessingResults …Run Code Online (Sandbox Code Playgroud) 从Guava 10开始,MapMaker.softKeys不推荐使用,并且不存在相应的方法CacheBuilder.
为什么要做出这种改变?使用它的现有代码需要做什么?
GNU特洛伊库是线程安全的吗?我对TObjectDoubleHashMap特别感兴趣.我查看了他们的文档,但它没有提到任何内容,那么我们是否应该假设它不是线程安全的?
在Guava 10+中,Google弃用了Files.deleteDirectoryContents().JavaDoc说
已过时.该方法存在差的符号链检测和竞争条件.只有通过外壳操作系统命令(例如rm -rf或del/s)才能适当地支持此功能.计划在Guava版本11.0中从Guava中删除此方法
我很困惑为什么会有竞争条件.我认为使用这种方法实际上是有用的,并找到一个糟糕的解决方案.作者可以分享为什么做出这个决定?
java ×12
guava ×11
collections ×2
trove4j ×2
algorithm ×1
bigdecimal ×1
comparator ×1
deprecated ×1
enums ×1
hashcode ×1