【发布时间】:2015-02-06 15:53:20
【问题描述】:
我需要从带有键(自定义对象)和值作为自定义对象集的 Map 创建一个哈希码,我使用 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());
}
谁能解释一下我做错了什么?
【问题讨论】:
-
只有一件事......你使用番石榴,那你为什么不使用
Multimap? -
除此之外,疯狂猜测:订购!请记住,没有任何东西可以保证
HashMap的键/值的顺序,也不能保证HashSet的值的顺序。我相信这是这里的问题。 -
这部分代码真的太老了,重写包含这个映射的域对象太贵了。我们没有时间。
-
是的,可以订购,我也在考虑。我试图做出这样的改进 Collections.sort(positions.entrySet()) 没有帮助
-
这不是您遇到的唯一问题。您的套装也需要订购。