Java:最终字段树映射更改大小

Java:最终字段树映射更改大小,java,Java,我有一个java代码,其中包含一个类TRADE_HISTORY,它保存交易历史 类TRADE_HISTORY有一个名为fMapDateOutputPriceRatios的最终字段,该字段在构造函数中设置。fMapDateOutputPriceRatios是日期和双数组(TreeMap)之间的映射。在构造函数中,使用 fMapDateOutputPriceRatios = new TreeMap<Date, double[]>(aOutputPriceRatioData); 发生此

我有一个java代码,其中包含一个类TRADE_HISTORY,它保存交易历史

类TRADE_HISTORY有一个名为fMapDateOutputPriceRatios的最终字段,该字段在构造函数中设置。fMapDateOutputPriceRatios是日期和双数组(TreeMap)之间的映射。在构造函数中,使用

fMapDateOutputPriceRatios = new TreeMap<Date, double[]>(aOutputPriceRatioData); 
发生此错误是因为日期不可用

尝试调试错误时,正在打印日期的大小

施工期间,尺寸为1973个单元

发生错误时,大小为1964个元素

特别是,发生错误时,2011年4月11日的日期不可用

我使用的是eclipse,并在修改字段时将变量fMapDateOutputPriceRatios设置为break。它只在构造期间中断

关于如何确定fMapDateOutputPriceRatios的大小发生变化的原因有何建议

访问fMapDateOutputPriceRatios的唯一行是

TRADE_HISTORY::TRADE_HISTORY(Map<Date, double[]> aOutputPriceRatioData )
        fMapDateOutputPriceRatios = new TreeMap<Date, double[]>(aOutputPriceRatioData); 
        Set<Date> dates = fMapDateOutputPriceRatios.keySet();  // Used to debug error

TRADE_HISTORY::public void addTradeDistribution_0_to_100(Date aDate, ...)
        outputPriceRatios = fMapDateOutputPriceRatios.get( aDate )  // Causes error
        Set<Date> dates = fMapDateOutputPriceRatios.keySet();   // Used to debug error
TRADE_HISTORY::TRADE_HISTORY(地图aOutputPriceRatioData)
fMapDateOutputPriceRatios=新树映射(aOutputPriceRatioData);
设置日期=fMapDateOutputPriceRatios.keySet();//用于调试错误
交易历史::公共作废添加交易分配0到100(日期日期日期,…)
outputPriceRatios=fMapDateOutputPriceRatios.get(aDate)//导致错误
设置日期=fMapDateOutputPriceRatios.keySet();//用于调试错误

首先,重要问题:您确定用作键的日期不会在任何地方修改吗?Date应该是一个不可变的对象,但它仍然包含旧的不推荐使用的方法,允许用户更改密钥内容。这将对TreeMap造成不可预测的后果,包括您描述的后果

此外,请确保所有日期的小时/分钟/秒/毫秒清除为0

现在,假设日期是不可变的:

实际上,您已经观察到密钥集大小的减少,这意味着对内容进行了物理修改。我知道它如何发生的唯一方法是由两个或多个线程并发访问映射

树映射必须在添加新键时重建树。也就是说,取消部分树的链接,然后将其重新链接到树中的其他位置。在此期间,如果另一个线程访问相同的结构并执行相同的操作,则该子树可能会丢失,从而导致键数减少

因此,作为第一步,尝试在同步块中访问此字段:

synchronized(fMapDateOutputPriceRatios) {
    outputPriceRatios = fMapDateOutputPriceRatios.get( aDate )
}

另外,我实际上没有在代码中的任何地方看到put(),但它必须在那里,没有奇迹

首先,重要的问题:您确定用作键的日期不会在任何地方修改吗?Date应该是一个不可变的对象,但它仍然包含旧的不推荐使用的方法,允许用户更改密钥内容。这将对TreeMap造成不可预测的后果,包括您描述的后果

此外,请确保所有日期的小时/分钟/秒/毫秒清除为0

现在,假设日期是不可变的:

实际上,您已经观察到密钥集大小的减少,这意味着对内容进行了物理修改。我知道它如何发生的唯一方法是由两个或多个线程并发访问映射

树映射必须在添加新键时重建树。也就是说,取消部分树的链接,然后将其重新链接到树中的其他位置。在此期间,如果另一个线程访问相同的结构并执行相同的操作,则该子树可能会丢失,从而导致键数减少

因此,作为第一步,尝试在同步块中访问此字段:

synchronized(fMapDateOutputPriceRatios) {
    outputPriceRatios = fMapDateOutputPriceRatios.get( aDate )
}

另外,我实际上没有在代码中的任何地方看到put(),但它必须在那里,没有奇迹

对对象实例的最终引用不会使该实例不可变!它仅阻止更改引用以指向不同的对象实例。引用是最终的,而不是它引用的对象实例的状态


请注意,
keySet()
返回的键集由映射支持。如果从中删除键,则相应的映射将从
fMapDateOutputPriceRatios
中删除。您是在修改日期还是在调试之外使用它?

对对象实例的最终引用不会使该实例不可变!它仅阻止更改引用以指向不同的对象实例。引用是最终的,而不是它引用的对象实例的状态


请注意,
keySet()
返回的键集由映射支持。如果从中删除键,则相应的映射将从
fMapDateOutputPriceRatios
中删除。您是在修改日期还是在调试之外使用它?

谢谢您的反馈

将日期/输出价格映射移动到驱动函数可消除日期/输出价格映射出现问题的可能性。 但是,仍然会出现意外错误

向TRADE_HISTORY的构造函数中添加了一个静态计数器,以跟踪构造的TRADE_HISTORY的数量。此外,一个整数id被添加到构造函数中并设置为等于计数器,因此id应该是1、2、3

当当前错误发生时,将打印交易记录id,该id为零,不应出现。在TRADE_历史实例的构造函数中需要进行更多的调试。似乎存在未正确构建的交易历史记录


如果需要更多帮助,将开始另一个问题。

谢谢您的反馈

将日期/输出价格映射移动到驱动函数可消除日期/输出价格映射出现问题的可能性。 但是,仍然会出现意外错误

向TRADE_HISTORY构造函数添加了一个静态计数器,以跟踪TRADE_HISTORY con的数量
synchronized(fMapDateOutputPriceRatios) {
    outputPriceRatios = fMapDateOutputPriceRatios.get( aDate )
}