【问题标题】:Strange results when using nested generics in java在 java 中使用嵌套泛型时出现奇怪的结果
【发布时间】:2014-02-02 12:14:21
【问题描述】:

我正在处理当前使用该结构的代码块。

HashMap(Text, HashMap(Text, ArrayList(Ints)))

HashMapWritable<Text, ArrayListOfIntsWritable> fileMap =
    new HashMapWritable<Text, ArrayListOfIntsWritable>();
HashMapWritable<Text, HashMapWritable<Text, ArrayListOfIntsWritable>> wordMap =
    new HashMapWritable<Text, HashMapWritable<Text, ArrayListOfIntsWritable>>(); 

我得到了奇怪的结果,但无法确定原因。

if (!wordMap.containsKey(newText)) {
  ArrayListOfIntsWritable wordPosition = new ArrayListOfIntsWritable();
  wordPosition.add(c);
  fileMap.put(INPUTFILE, wordPosition);
  wordMap.put(newText, fileMap);                    
} else {
  HashMapWritable<Text, ArrayListOfIntsWritable> updatePosStep1 =
      wordMap.get(newText);
  ArrayListOfIntsWritable updatePosStep2 = updatePosStep1.get(INPUTFILE);
  updatePosStep2.add(c);
}

我也尝试过更新:

wordMap.get(newText).get(INPUTFILE).add(c);

但结果相同。

这都是在一个循环中完成的,发生的事情是这样的(示例显示了 'newText' = 'episod' 的情况,其中数字是它们在循环中的位置(循环递增 c 的基本)和 [ int,int,...] 是已经存储的 C 的值

 Word: episod curPos 14 positions: [14]
 Word: episod curPos 120 positions: [116, 118, 120]
 Word: episod curPos 191 positions: [186, 190, 191]
 Word: episod curPos 199 positions: [198, 199]

如您所见(希望它显示了我想要了解的内容),键 episod 的值在之前的某个时间点被重置。这对所有单词都是一样的,所以当它完成运行时,所有单词都有相同的几组整数..

我做错了什么明显吗?

【问题讨论】:

  • ArrayListOfIntsWritable 和 HashMapWritable 有哪些类?
  • Java HashMap 的可写扩展。这个泛型类支持使用任何类型作为键或值。对于特征向量,HMapKIW、HMapKFW 和一系列相关类提供了更高效的实现。此类与 Hadoop 的 MapWritable 之间有许多关键区别: MapWritable 更灵活,因为它支持异构元素。在这个类中,所有的键必须是相同的类型,所有的值必须是相同的类型。这种假设允许更简单的序列化协议,因此更有效。
  • ArrayListOfInts 类的可写扩展。此类提供了一种高效的数据结构来存储 MapReduce 作业的整数列表。 (github.com/lintool/Cloud9/blob/master/src/dist/edu/umd/cloud9/…)
  • Text 是可变类吗(所以hashCode() 可能会产生不同的结果,因此将新的键/值对存储到映射中)?如果是这样,您应该将其替换为不可变的mutable keys shouldn't be used for keys。可能您所要做的就是覆盖hashCode()equals(Object)toString()Text
  • 这是我第一个想到的 Roman,但如果它再次看到它,它不会重新初始化这个词,我做了一些日志记录以仔细检查,一旦它被实例化一次,它就会移动到“else”所以它与嵌套的 .add (我认为)有关

标签: java generics arraylist hashmap


【解决方案1】:

这真的很令人困惑,您在“真”条件下使用外部方式创建的对象“fileMap”,而在“假”条件下从地图接收“updatePosStep1”。 猜测,您正在共享相同的“fileMap”实例,或者在呈现代码之前的某些条件下重新创建/重置“fileMap”。

因此,您可能会不小心在“wordPosition”中有额外的值,并且在每个新的“newText”处重新创​​建“wordPosition”。

if (!wordMap.containsKey(newText)) {
  final HashMapWritable<Text, ArrayListOfIntsWritable> fileMap = new HashMapWritable<Text, ArrayListOfIntsWritable>;
  final ArrayListOfIntsWritable wordPosition = new ArrayListOfIntsWritable();
  wordPosition.add(c);
  fileMap.put(INPUTFILE, wordPosition);
  wordMap.put(newText, fileMap);                    
} else {
  final HashMapWritable<Text, ArrayListOfIntsWritable> fileMap =
      wordMap.get(newText);
  final ArrayListOfIntsWritable wordPosition = fileMap.get(INPUTFILE);
  wordPosition.add(c);
}

【讨论】:

  • 哦,你这个可爱的人。你是绝对正确的,现在有道理了,文件映射的重用完全抛弃了一切,你让我的一天免于浪费
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-01-18
  • 2018-06-27
  • 2019-09-22
  • 1970-01-01
  • 1970-01-01
  • 2013-03-26
  • 2013-01-08
相关资源
最近更新 更多