jjzjj

java - 允许分别提供相等比较器和散列函数的映射

coder 2024-03-28 原文

在尝试对多项式建模时,尤其是它们的乘法,我遇到了以下问题。在乘法过程中,两个多项式的各个单项式相乘,当然我可能会得到 (3x^2 y + 5x y^2) * (x + y)。结果包含 3x^2 y^2 和 5 x^2 y^2,我想立即通过加法合并。

自然地,我想使用单项式的 x^2 y^2 部分作为(哈希)映射中的键来添加不同的系数(示例中的 3 和 5)。但是我设想的单项式对象自然也应该包含系数,它应该是映射键的一部分。

当然,我可以编写单项式对象的等号/哈希码,以便它们忽略系数。但这感觉非常错误,因为从数学上讲,单项式显然只有在系数也相等的情况下才等于另一个单项式。

为中间操作引入无系数的单项式对象看起来也不对。

我可以不使用 map ,而是使用列表并使用带有忽略系数的专用比较器的二进制搜索。

除了实现一个不使用键的等值/哈希码的映射,而是一个专用的映射,是否有关于如何融合单项式的更好的想法?

最佳答案

由于 [Linked]HashMap 的 JDK 实现不允许您覆盖 equals/hashCode 实现,唯一的其他方法是:

  • 像这样的包装对象:

      class A {
        private final String fieldA; // equals/hashCode based on that field.
        private final String fieldB; // equals/hashCode based on that field.
      }
    
      class B {
        private A a;
        public int hashCode() {return a.fieldA.hashCode();} 
        public boolean equals(Object o) {... the same ... }
      }
    
      Map<B, Value> map = new HashMap<B, Value>();
      map.put(new B(new A("fieldA", "fieldB")), new Value(0));
    

    好吧,有更多的 getters/constructors。

    这可能很烦人,也许存在一些库(如 Guava)允许提供 equals/hashCode 方法,就像您可以将 Comparator 提供给 TreeMap .

    您将在下面找到一个示例实现,其中指出了如何装饰现有 map 。

  • 使用带有特定比较器TreeMap。另一个答案指向它,但我会说你需要正确定义一个 Comparator 因为这可能会导致问题:如果你的 compareTo 方法在相等时返回 0达到,在其他情况下为 1,这意味着没有自然排序。您应该尝试找到一个,或使用包装器对象。


如果您想接受挑战,您可以在另一个 HashMap 上使用委托(delegate)/装饰创建一个基本实现(这可能是另一种映射,如 LinkedHashMap) :

public class DelegatingHashMap<K,V> implements Map<K,V> {
  private final BiPredicate<K,Object> equalsHandler;
  private final IntFunction<K> hashCodeHandler;
  private final Map<Wrapper<K>,V> impl = new HashMap<>();

  public DelegatingHashMap(
    BiPredicate<K,Object> equalsHandler,
    IntFunction<K> hashCodeHandler
  ) {
    this.equalsHandler = requireNonNull(equalsHandler, "equalsHandler");
    this.hashCodeHandler= requireNonNull(hashCodeHandler, "hashCodeHandler");
  }

  public Object get(K key) {
    Wrapper<K> wrap = new Wrapper<>(key);
    return impl.get(wrap);
  }  

  ...

  static class Wrapper<K2> {
    private final K2 key;
    private final BiPredicate<K> equalsHandler;
    private final IntFunction<K> hashCodeHandler;
    public int hashCode() {return hashCodeHandler.apply(key);}
    public boolean equals(Object o) {
      return equalsHandler.test(key, o);
    }
  }
}

以及使用 map 的代码:

DelegatingHashMap<String, Integer> map = new DelegatingHashMap<>(
  (key, old) -> key.equalsIgnoreCase(Objects.toString(o, "")),
  key -> key.toLowerCase().hashCode()
);
map.put("Foobar", 1);
map.put("foobar", 2);

System.out.println(map); // print {foobar: 2}

但也许最好的(为了内存)是重写 HashMap 以直接使用处理程序而不是包装器。

关于java - 允许分别提供相等比较器和散列函数的映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25773886/

有关java - 允许分别提供相等比较器和散列函数的映射的更多相关文章

  1. ruby - 将散列转换为嵌套散列 - 2

    这道题是thisquestion的逆题.给定一个散列,每个键都有一个数组,例如{[:a,:b,:c]=>1,[:a,:b,:d]=>2,[:a,:e]=>3,[:f]=>4,}将其转换为嵌套哈希的最佳方法是什么{:a=>{:b=>{:c=>1,:d=>2},:e=>3,},:f=>4,} 最佳答案 这是一个迭代的解决方案,递归的解决方案留给读者作为练习:defconvert(h={})ret={}h.eachdo|k,v|node=retk[0..-2].each{|x|node[x]||={};node=node[x]}node[

  2. ruby - Ruby 的 Hash 在比较键时使用哪种相等性测试? - 2

    我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。

  3. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  4. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  5. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  6. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

  7. ruby - 按值降序排列散列,然后按升序键入 ruby - 2

    我有这样的哈希trial_hash={"key1"=>1000,"key2"=>34,"key3"=>500,"key4"=>500,"key5"=>500,"key6"=>500}我按值降序排列:my_hash=trial_hash.sort_by{|k,v|v}.reverse我现在是这样理解的:[["key1",1000],["key4",500],["key5",500],["key6",500],["key3",500],["key2",34]]但我希望当值相同时按键的升序排序。我该怎么做?例如:上面的散列将以这种方式排序:[["key1",1000],["key3",500

  8. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  9. ruby-on-rails - RSpec:避免使用允许接收的任何实例 - 2

    我正在处理旧代码的一部分。beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)endRubocop错误如下:Avoidstubbingusing'allow_any_instance_of'我读到了RuboCop::RSpec:AnyInstance我试着像下面那样改变它。由此beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)end对此:let(:sport_

  10. ruby-on-rails - ActiveRecord 对象相等 - 2

    根据ActiveRecord::Base的文档:==(comparison_object)Returnstrueifcomparison_objectisthesameexactobject,orcomparison_objectisofthesametypeandselfhasanIDanditisequaltocomparison_object.id.Notethatnewrecordsaredifferentfromanyotherrecordbydefinition,unlesstheotherrecordisthereceiveritself.Besides,ifyoufet

随机推荐