gpt4 book ai didi

java - Guava Hasher 有时对同一对象给出不同的结果

转载 作者:行者123 更新时间:2023-12-01 18:18:12 28 4
gpt4 key购买 nike

我需要使用键(自定义对象)和值作为自定义对象集从映射创建哈希码,我使用 Guava 18.0

@Getter
public final class StockKey {

@ValidIsin
private final String isin;

@ValidExchangeId
private final Integer exchangeId;

@ValidCurrency
private final String currency
}


@EqualsAndHashCode
public final class ClientAssetPosition {

public static final double EPSILON = 0.0001;

@NotNull
private final PositionType type;

@NotNull
private final Double quantity;

@Nullable
@Getter
private Double coveredOptions;

@Nullable
@Getter
private Double blockedCoveringUnderlyings;

@Getter
@Setter
private Boolean excluded;
}

所以我有一个创建 HashCode 的函数

 public static HashCode getHashCodeWithSha256(Map<StockKey, Set<ClientAssetPosition>> positions) {
final Hasher hasher = Hashing.sha256().newHasher();
for (Map.Entry<StockKey, Set<ClientAssetPosition>> positionsEntry : positions.entrySet()) {
hasher.putObject(positionsEntry.getKey(), STOCK_KEY_FUNNEL);
for (ClientAssetPosition asset : positionsEntry.getValue()) {
hasher.putObject(asset, CLIENT_ASSET_POSITION_FUNNEL);
}
}
return hasher.hash();
}

我用这样的漏斗

public static final Funnel<StockKey> STOCK_KEY_FUNNEL = new Funnel<StockKey>() {
@Override
public void funnel(StockKey from, PrimitiveSink into) {
into.putString(from.getIsin()).putString(from.getCurrency()).putInt(from.getExchangeId());
}
};
public static final Funnel<ClientAssetPosition> CLIENT_ASSET_POSITION_FUNNEL = new Funnel<ClientAssetPosition>() {
@Override
public void funnel(ClientAssetPosition from, PrimitiveSink into) {
into.putDouble(from.getQuantity()).putString(from.getType().name());
}
};

对于同一个Map,这个函数有时会返回不同的HashCode我通过这个单元测试找到了它。如果从 Maven 运行此测试会失败,但并非每次都会失败。

@Test
public void testSamePortfolioSameHAshCodeOrdersASC(){
Map<StockKey, Set<ClientAssetPosition>> positions = new HashMap<>();
positions.put(PredefinedStockKeys.UBS, Sets.newHashSet(PredefinedAssetPosition.OWN_1, PredefinedAssetPosition.ORD_B101));
positions.put(PredefinedStockKeys.UBS_FEB_12_17_C, Sets.newHashSet(PredefinedAssetPosition.OWN_1, PredefinedAssetPosition.ORD_B101));
positions.put(PredefinedStockKeys.UBSN_MAR12_12_5_C, Sets.newHashSet(PredefinedAssetPosition.OWN_1, PredefinedAssetPosition.ORD_M10));
positions.put(PredefinedStockKeys.UBSN_MAR12_12_5_P, Sets.newHashSet(PredefinedAssetPosition.OWN_1, PredefinedAssetPosition.ORD_B101));
positions.put(PredefinedStockKeys.UBSN_MAR12_13_C, Sets.newHashSet(PredefinedAssetPosition.OWN_1, PredefinedAssetPosition.ORD_B101));
positions.put(PredefinedStockKeys.UBSN_MAY12_13_C, Sets.newHashSet(PredefinedAssetPosition.C_ORD_M1, PredefinedAssetPosition.ORD_M10));
positions.put(PredefinedStockKeys.UBSN_MAR12_13_P, Sets.newHashSet(PredefinedAssetPosition.OWN_1, PredefinedAssetPosition.ORD_B101));
positions.put(PredefinedStockKeys.UBS_JAN_12_17_C, Sets.newHashSet(PredefinedAssetPosition.OWN_1, PredefinedAssetPosition.C_ORD_M1));
positions.put(PredefinedStockKeys.UBS_JAN_12_17_P, Sets.newHashSet(PredefinedAssetPosition.OWN_1, PredefinedAssetPosition.ORD_B101));
positions.put(PredefinedStockKeys.UBSH_APR12, Sets.newHashSet(PredefinedAssetPosition.C_ORD_M1, PredefinedAssetPosition.ORD_B101));
positions.put(PredefinedStockKeys.UBSH_MAR12, Sets.newHashSet(PredefinedAssetPosition.C_ORD_M1, PredefinedAssetPosition.ORD_B101));
positions.put(PredefinedStockKeys.UBSH_MAY12, Sets.newHashSet(PredefinedAssetPosition.C_ORD_M1, PredefinedAssetPosition.ORD_B101));

Map<StockKey, Set<ClientAssetPosition>> positionsv2 = new HashMap<>();
positionsv2.put(PredefinedStockKeys.UBS, Sets.newHashSet(PredefinedAssetPosition.OWN_1, PredefinedAssetPosition.ORD_B101));
positionsv2.put(PredefinedStockKeys.UBSN_MAR12_12_5_C, Sets.newHashSet(PredefinedAssetPosition.OWN_1, PredefinedAssetPosition.ORD_M10));
positionsv2.put(PredefinedStockKeys.UBSN_MAR12_12_5_P, Sets.newHashSet(PredefinedAssetPosition.OWN_1, PredefinedAssetPosition.ORD_B101));
positionsv2.put(PredefinedStockKeys.UBSH_APR12, Sets.newHashSet(PredefinedAssetPosition.C_ORD_M1, PredefinedAssetPosition.ORD_B101));
positionsv2.put(PredefinedStockKeys.UBSN_MAY12_13_C, Sets.newHashSet(PredefinedAssetPosition.C_ORD_M1, PredefinedAssetPosition.ORD_M10));
positionsv2.put(PredefinedStockKeys.UBSN_MAR12_13_P, Sets.newHashSet(PredefinedAssetPosition.OWN_1, PredefinedAssetPosition.ORD_B101));
positionsv2.put(PredefinedStockKeys.UBS_JAN_12_17_C, Sets.newHashSet(PredefinedAssetPosition.OWN_1, PredefinedAssetPosition.C_ORD_M1));
positionsv2.put(PredefinedStockKeys.UBS_JAN_12_17_P, Sets.newHashSet(PredefinedAssetPosition.OWN_1, PredefinedAssetPosition.ORD_B101));
positionsv2.put(PredefinedStockKeys.UBS_FEB_12_17_C, Sets.newHashSet(PredefinedAssetPosition.OWN_1, PredefinedAssetPosition.ORD_B101));
positionsv2.put(PredefinedStockKeys.UBSH_MAR12, Sets.newHashSet(PredefinedAssetPosition.C_ORD_M1, PredefinedAssetPosition.ORD_B101));
positionsv2.put(PredefinedStockKeys.UBSN_MAR12_13_C, Sets.newHashSet(PredefinedAssetPosition.ORD_B101, PredefinedAssetPosition.OWN_1));
positionsv2.put(PredefinedStockKeys.UBSH_MAY12, Sets.newHashSet(PredefinedAssetPosition.C_ORD_M1, PredefinedAssetPosition.ORD_B101));
HashCode hashCodeWithSha256Expected = HashHelper.getHashCodeWithSha256(positions);
HashCode hashCodeWithSha256Exist = HashHelper.getHashCodeWithSha256(positionsv2);
Assert.assertArrayEquals(hashCodeWithSha256Expected.asBytes(), hashCodeWithSha256Exist.asBytes());
}

有人可以解释一下我做错了什么吗?

最佳答案

我认为问题与订购有关。即使从一个调用到另一个调用,如果您分别将相同的键/值对或值放入 HashMapHashSet 中,也无法保证条目的顺序会发生变化。两次调用之间保持不变。当然,跨 JVM 运行的情况要少得多。

因此,您需要重写哈希计算方法,以便在计算哈希之前强制执行命令...

由于您使用 Guava,这很简单:使用 Ordering.sortedCopy()

这应该可以做到;但是,请注意,这假设您的 StockKeyClientAssetPosition 类实现 Comparable:

public static HashCode getHashCodeWithSha256(Map<StockKey, Set<ClientAssetPosition>> positions) 
{
final Hasher hasher = Hashing.sha256().newHasher();

final Iterable<StockKey> orderedKeys
= Ordering.sortedCopy(positions.keySet());

Iterable<ClientAssetPosition> orderedAssets;

for (final StockKey key: orderedKeys) {
hasher.putObject(key, STOCK_KEY_FUNNEL);

orderedAssets = Ordering.sortedCopy(positions.get(key));

for (final ClientAssetPosition asset: orderedAssets)
hasher.putObject(asset, CLIENT_ASSET_POSITION_FUNNEL);
}
return hasher.hash();
}
<小时/>

但是:确实考虑切换到Multimap。请记住,如果您在某些时候需要向后兼容,它还有一个 .asMap() 方法。

关于java - Guava Hasher 有时对同一对象给出不同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28369607/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com