就像在XY坐标系中,一个X刻度、一个Y刻度,会对应图上的一个点,即pair(x, y) – > point,那么就有创建一个点,或者根据(x, y)来寻求一个点的需求,如果用Python的语法表达,是这个样子:
1
|
dict
(
(
x
,
y
)
:
point
)
|
然而在JAVA中却变得不容易,骨钩了一下,有这么一些方法:
使用嵌套MAP
1
2
3
4
|
Map
<
Integer
,
Map
<
Integer
,
V
>>
map
=
//...
// ...
map
.
get
(
2
)
.
get
(
5
)
;
|
这种方法将水平的KEY切换成了垂直KEY,我们要找寻XY坐标系中(x, y)对应的点,其实可以先找x点的那条垂直线,然后找出这条垂直线上y高度的那个点。
但是要取得这个双KEY的VALUE,得有2次GET,实例代码没有做第一次GET的NULL判断,有隐患!并且感觉不是很直观。
写一个pair key的包装类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
public
class
Key
{
private
final
int
x
;
private
final
int
y
;
public
Key
(
int
x
,
int
y
)
{
this
.
x
=
x
;
this
.
y
=
y
;
}
@Override
public
boolean
equals
(
Object
o
)
{
if
(
this
==
o
)
return
true
;
if
(
!
(
o
instanceof
Key
)
)
return
false
;
Key
key
=
(
Key
)
o
;
return
x
==
key
.
x
&&
y
==
key
.
y
;
}
@Override
public
int
hashCode
(
)
{
int
result
=
x
;
result
=
31
*
result
+
y
;
return
result
;
}
}
|
以这种方法提前包装好一个类,类中有x和y两个属性,同时提供equals方法用于“点”的比较,提供hashCode用于使用在计算对象在散列表中的位置。
为什么要覆盖hashCode方法?请参见链接
写完这个pair类之后,就好用了:
1
2
3
4
|
Map
<
Key
,
V
>
map
=
//...
map
.
get
(
new
Key
(
2
,
5
)
)
;
|
这种方法以更多的代码为代价来实现pair key的map,pair class的编写中,不能忘记覆盖equals和hashcode方法,增加了代码量,感觉不是很好用。
GOOGLE的HashBasedTable类库
这种方法感觉才是最直观,最好用的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
import
com
.
google
.
common
.
collect
.
HashBasedTable
;
import
com
.
google
.
common
.
collect
.
Table
;
// 创建
Table
<
Long
,
Long
,
Point
>
plane
=
HashBasedTable
.
create
(
)
;
// 新增
plane
.
put
(
1L
,
2L
,
pointA
)
;
plane
.
put
(
1L
,
3L
,
pointB
)
;
plane
.
put
(
1L
,
4L
,
pointC
)
;
// 获取
Point
pointA
=
plane
.
get
(
1L
,
2L
)
;
Point
pointB
=
plane
.
get
(
1L
,
2L
)
;
|
惊叹,好用。在JAVA语言里,写成这样的代码,可称之为艺术。
无限维度的KEY
有两种方法可以实现无线维度的KEY,第一种和本文的第二种方法一样,先写一个CLASS,里面有无限个属性,然后作为MAP的KEY。
第二种,如果类型一样,可以这样子实现:
1
|
Map
<
List
<Integer>
,
V
>
map
=
//...
|
但是这种方法易出错、不易读,并且性能很低。
总结
要实现map的key是两个绑定的属性,或者称之为pair key,个人认为首先使用google的HashBasedTable类库,其次的方法是编写对应的class。
可是,这些总感觉不是那么的方便,python那种{tuple : value}的方法,咋就那么艺术呢!
本文翻译自:链接 中的一个答案。