Nashorn,Java集合,如何在纯javascript中实现equals和hashCode
我面临着以下问题。我想在Nashorn脚本中使用Nashorn,Java集合,如何在纯javascript中实现equals和hashCode,java,javascript,equals,hashcode,nashorn,Java,Javascript,Equals,Hashcode,Nashorn,我面临着以下问题。我想在Nashorn脚本中使用java.util.HashMap和java.util.PriorityQueue,其中我需要使用特定的自定义对象作为HashMap中的键,还需要使用HashMap.containsKey()检查映射中是否有键(另一个选项是检查集合中的对象是否包含)(对象(o)) 所以,很明显,我需要基于一些字段值在对象中实现equals和hashCode 例如: 试图使用JavaScript。由于JavaScript没有这些方法,因此无法工作。请参阅示例1和示例
java.util.HashMap
和java.util.PriorityQueue
,其中我需要使用特定的自定义对象作为HashMap中的键,还需要使用HashMap.containsKey()
检查映射中是否有键(另一个选项是检查集合中的对象是否包含)(对象(o))
所以,很明显,我需要基于一些字段值在对象中实现equals和hashCode
例如:
- 如何使用参数插入构造函数
- 如何从这个:[object]转换到其他:jdk.nashorn.javaadapters.java.lang。Object@0,反之亦然
var PriorityQueue=java.util.PriorityQueue;
var HashMap=java.util.HashMap;
var Integer=java.lang.Integer;
//样本1
//不起作用,没有调用equals和hashCode
函数顶点1(起始、成本){
this.from=from;
成本=成本;
this.equals=函数(其他){返回this.from==other.from;}
this.hashCode=function(){返回整数.hashCode(this.from);}
}
var hm=新的HashMap();
hm.put(新顶点1(1,10),10);
hm.put(新顶点1(1,20),21);
//照片尺寸是2号,但我想看1号
打印(“哈希映射大小:+hm.size());
//打印错误
打印(“HashMap1包含:”+hm.containsKey(新的顶点1(1,20)));
// ------------------------------------------------------------------
//样本2
//不起作用,没有调用equals和hashCode
函数顶点1(起始、成本){
this.from=from;
成本=成本;
}
Vertex1.prototype={
等于:函数(其他){返回this.from==other.from;},
hashCode:function(){return Integer.hashCode(this.from);},
}
var hm=新的HashMap();
hm.put(新顶点1(1,10),10);
hm.put(新顶点1(1,20),21);
//照片尺寸是2号,但我想看1号
打印(“哈希映射大小:+hm.size());
//打印错误
打印(“HashMap1包含:”+hm.containsKey(新的顶点1(1,20)));
// ------------------------------------------------------------------
//样本3
//部分工作,正在调用方法。但是
//1.如何使用参数插件Constructor?
//2.如何从这个:[object]转换到其他:jdk.nashorn.javaadapters.java.lang。Object@0,反之亦然
var JObject=Java.type(“Java.lang.Object”);
var Vertex2=Java.extend(JObject{
起:0,,
equals:function(other){返回this.from.equals(other.from);},
hashCode:function(){return Integer.hashCode(this.from);},
});
var hm=新的HashMap();
//如何为新的顶点2(10,10)实现构造函数?
hm.put(新顶点2(),10);
hm.put(新顶点2(),21);
//打印大小为2,因为hashCode相同且等于返回false
打印(“哈希映射大小:+hm.size());
//打印false,因为equals返回false
打印(“HashMap1包含:”+hm.containsKey(新的顶点2()));
// ------------------------------------------------------------------
//样本4
//MyObject是用Java实现的,可以工作,但是Nashorn是不明确的!!!
var MyObject=Java.type(“com.arsenyko.MyObject”);
var Vertex2=Java.extend(MyObject,{});
var hm=新的HashMap();
hm.put(新顶点2(1,10,10);
hm.put(新顶点2(1,20,21);
打印(“哈希映射大小:+hm.size());
打印(“HashMap1包含:”+hm.containsKey(新的顶点2(1,10)));
编辑1
@Tomasz,谢谢。已经看到了所有提到的链接。但是尽管存在一些未记录的链接。几乎放弃了Nashorn。到了下面的部分解决方案,调用了方法,使用了构造函数,但是如何在方法中强制转换其他。from
等于方法,以便从访问原始对象的ode>字段(此代码为顶点的每个实例生成不同的类):
//加载(“nashorn:mozilla_compat.js”);
var PriorityQueue=java.util.PriorityQueue;
var HashMap=java.util.HashMap;
var Integer=java.lang.Integer;
函数顶点1(起始、成本){
this.from=from;
成本=成本;
this.equals=函数(其他){
var value1=此值为从;
//如何从这里得到其他的???
var值2=其他来源;
打印('value1='+value1+'value2='+value2);
印刷品(其他);
var eq=值1。等于(值2);
打印('equals is'+eq);
返回均衡器;
}
this.hashCode=函数(){
var hashCode=Integer.hashCode(this.from);
打印('hashCode为'+hashCode');
返回哈希码;
}
var JObject=Java.type(“Java.lang.Object”);
//返回Java.extend(JObject,this);//不起作用
//返回此;//不起作用
//返回新的JavaAdapter(java.lang.Object,this);//使用load(“nashorn:mozilla_compat.js”);
var Type=Java.extend.apply(Java[JObject]);
返回新类型(此);
}
var hm=新的HashMap();
hm.put(新顶点1(1,10),10);
hm.put(新顶点1(1,20),21);
//照片尺寸是2号,但我想看1号
打印(“哈希映射大小:+hm.size());
//打印错误
打印(“HashMap包含:”+hm.containsKey(新的顶点1(1,20)));
编辑2
感谢Tomasz,正如他所指出的,每次使用特定于类的实现对象调用Java.extend()函数都会生成一个新的Java适配器类
var vertex = new JavaAdapter(java.lang.Object, new Vertex(1, 10));
hm.put(vertex, 10);
load("nashorn:mozilla_compat.js");
// we will need a factory method
var createVertex = (function() { // i hope you are familiar with "inline" function calls
// private variables used in every call of factory method - but initialized once
var
JObjExtender = Java.extend(Java.type("java.lang.Object")),
JInteger = Java.type("java.lang.Integer"),
_equals = function(other) {
return this.from === other.from;
},
_hashCode = function() {
return JInteger.hashCode(+this.from); // leading "+" converts to number
};
// the "actual" factory method
return function(from, cost) {
return new JObjExtender() {
from : from,
cost : cost,
equals : _equals,
hashCode : _hashCode
};
};
})();
var vertex = createVertex(1, 10);
hm.put(vertex, 10);
var v1 = createVertex(1, 10);
var v2 = createVertex(1, 20);
var classEquals = (v1.class === v2.class); // produces : true
var v1 = new java.lang.Object(new JSVertex(10, 10));
// produces: TypeError: Can not construct java.lang.Object with the passed
// arguments; they do not match any of its constructor signatures.
var JSVertex = function (from, cost) {
this.from = from;
this.cost = cost;
};
JSVertex.prototype = {
equals : function(other) {
return this.from === other.from;
},
hashCode : function() {
return java.lang.Integer.hashCode(+this.from); // leading "+" converts to number
},
compare : function(other) {
return this.from - (+other.from);
}
};
var v1 = new java.lang.Comparable(new JSVertex(10, 10));
print(v1.class);
// produces both: class jdk.nashorn.javaadapters.java.lang.Object and
// class jdk.nashorn.javaadapters.java.lang.Comparable
var v2 = new java.lang.Comparable(new JSVertex(11, 12));
print(v2 instanceof java.lang.Object); // produces true
print(v2 instanceof java.lang.Comparable); // produces true
var JSVertex = function (from, cost) {
this.from = +from;
this.cost = +cost;
};
JSVertex.prototype = {
equals : function(other) {
print("[JSVertex.prototype.equals " + this + "]");
return this.from === other.from;
},
hashCode : function() {
var hash = java.lang.Integer.hashCode(this.from);
print("[JSVertex.prototype.hashCode " + this + " : " + hash + "]");
return hash;
},
toString : function() {
return "[object JSVertex(from: " +
this.from + ", cost: " + this.cost + ")]";
},
// this is a custom method not defined in any Java class or Interface
calculate : function(to) {
return Math.abs(+to - this.from) * this.cost;
}
};
var wrapJso = (function() {
var
JObjExtender = Java.extend(Java.type(
"jdk.nashorn.api.scripting.AbstractJSObject")),
_getMember = function(name) {
return this.jso[name];
},
_setMember = function(name, value) {
this.jso[name] = value;
},
_toString = function() {
return this.jso.toString();
};
return function(jsObject) {
var F = function() {};
F.prototype = jsObject;
var f = new F();
f.jso = jsObject;
f.getMember = _getMember;
f.setMember = _setMember;
f.toString = _toString; // "toString hack" - explained later
return new JObjExtender(f);
};
})();
var wrapped = wrapJso(new JSVertex(11,12));
// access custom js property and method not defined in any java class
// or interface.
print(wrapped.from);
print(wrapped.calculate(17));
print("--------------");
// call toString() and hashCode() from JavaScript on wrapper object
print(wrapped.toString());
print(wrapped.hashCode());
print("--------------");
// Use StringBuilder to make Java call toString() on our wrapper object.
print(new java.lang.StringBuilder().append(wrapped).toString() );
// see hack in wrapJso() - for some reason java does not see
// overriden toString if it is defined as prototype member.
// Do some operations on HashMap to get hashCode() mehod called from java
var map = new java.util.HashMap();
map.put(wrapped, 10);
map.get(wrapped);
wrapped.from = 77;
map.get(wrapped);
print("--------------");
// let's show that modyfing any of pair: wrapped or jso touches underlying jso.
var jso = new JSVertex(17,128);
wrapped = wrapJso(jso);
print(wrapped);
jso.from = 9;
wrapped.cost = 10;
print(wrapped);
print(jso);
print(jso == wrapped);
11
72
--------------
[object JSVertex(from: 11, cost: 12)]
[JSVertex.prototype.hashCode [object JSVertex(from: 11, cost: 12)] : 11]
11
--------------
[object JSVertex(from: 11, cost: 12)]
[JSVertex.prototype.hashCode [object JSVertex(from: 11, cost: 12)] : 11]
[JSVertex.prototype.hashCode [object JSVertex(from: 11, cost: 12)] : 11]
[JSVertex.prototype.hashCode [object JSVertex(from: 77, cost: 12)] : 77]
--------------
[object JSVertex(from: 17, cost: 128)]
[object JSVertex(from: 9, cost: 10)]
[object JSVertex(from: 9, cost: 10)]
false