java.util.arraylist哈希代码在storm拓扑上返回的值不是那么随机

hc2pp10m  于 2021-06-21  发布在  Storm
关注(0)|答案(2)|浏览(384)

我在为arraylist返回的hashcode中遇到了一个奇怪的问题。下面是修改后的tuple.clj(来自ApacheStorm源代码)。传递给列表哈希代码的列表是字符串列表。返回的哈希代码(返回的代码为%6)总是4。i、 e.“(mod(.hashcode)6)”始终为4。我真的很困惑到底出了什么问题。由于这个问题,跨下一个bolt任务的元组分布是不正确的。我不知道这里可能出了什么问题。同样的问题,我不认为我运行的东西从clojure repl。
我如何知道正在使用哪个hashcode函数?有没有办法检查clojure的java类方法的方法细节?

(ns backtype.storm.tuple
  (:use [backtype.storm bootstrap])
  )

(bootstrap)
(defn- print-comma-list [^List els ]
  (let [ret (StringBuilder. ) ]
    (do 
      (loop [iter (.iterator els) ]
        (when (.hasNext iter)
            (.append (.append ret (.next iter)) ",")
            (recur iter))))
      (.toString ret)))

(defn list-hash-code [^List alist comp-id group-id ]
  (do
    (if ( and (= comp-id "test1-bolt") ( = group-id "field1,"))
        (log-message "Hashcode returned: " (.hashCode alist) " mod val " (mod (.hashCode alist) 6) " " (print-comma-list alist)))
    (.hashCode alist)))
wgmfuz8q

wgmfuz8q1#

实施 hashcode 对于java ArrayList 完全不是“随机的”。
它实际上使用的是java中指定的算法 List 以可预测的方式组合元素哈希代码的api;看看这个javadoc。如果列表的元素具有可预测的顺序和可预测的哈希码,则列表哈希码是可预测的。
算法如下(在java中):

int hashCode = 1;
 for (E e : list)
     hashCode = 31 * hashCode + (e == null ? 0 : e.hashCode());

有没有办法检查clojure的java类方法的方法细节?
java源代码和javadocs是免费提供的。
但是,不支持从clojure检查“方法详细信息”。。。假设您感兴趣的“方法细节”是算法(实际上,java程序也不支持它!)我想,您可以通过编程查找字节码,并调用一些应用程序来反汇编或反编译它们。但没什么意义。。。考虑到 java.util.* 包含在每个oracle jdk安装程序中。

kmbjn2e3

kmbjn2e32#

如果调用.getclass.getcanonicalname,将获得实现所使用列表的类的全名。oraclejdk中默认抽象列表的hashcode包含在stephen c.的答案中。如果这是所使用的源代码,那么如果字符串不同,就不会有特殊的异常原因,尽管这取决于您的数据。
请注意,hashcode()根本不能保证均匀分布。只要equals()函数区分类的不同示例,hashcode()为类的所有示例返回1是正确的。这是因为hashcode表示“弱相等”,相等的对象必须具有相同的hashcode(例如,要通过hashmap正确找到),但反之则不成立。这意味着您可以将hashcode修改为其他内容,例如list,hashcode乘以一个素数,只要从旧hashcode到新hashcode的函数将相同的输入Map到相同的输出(没有随机元素)。

相关问题