移植Java代码到C++的技巧(整合)
作者:网络转载 发布时间:[ 2013/4/17 9:53:25 ] 推荐标签:
3、作为有序的关联性容器,键对象的排序机制自然是一个无法回避的问题,但幸运的是,尽管这两种容器在某些处理细节上存在一定的差异,然而整个排序机制的思路却是如出一辙,可以这样说,它们是神似而形不似,而造成“形不似”的主要原因则主要来自于这两种语言的本身。下面我们先介绍Java中TreeMap的键对象排序机制。
1)一种常用的方式是让键对象成为Comparable<T>接口的实现类,这样TreeMap的内部则可以利用接口方法compareTo()的返回值来判断该键对象在容器中所在的位置。见如下代码:
public class MyTest implements Comparable<MyTest> {
private int key;
public MyTest(int key) {
this.key = key;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof MyTest))
return false;
MyTest t = (MyTest)o;
System.out.println("equals of MyTest is called here.");
return key == t.key;
}
@Override
public int compareTo(MyTest o) {
return key - o.key;
}
public static void main(String[] args) {
TreeMap<MyTest,Integer> tm = new TreeMap<MyTest,Integer>();
tm.put(new MyTest(5), 5);
tm.put(new MyTest(2), 2);
tm.put(new MyTest(10), 10);
tm.put(new MyTest(10), 20);
for (Entry<MyTest,Integer> e : tm.entrySet())
System.out.println("Key = " + e.getKey().key + ", Value = " + e.getValue());
}
}
//compareTo of MyTest is called here.
//compareTo of MyTest is called here.
//compareTo of MyTest is called here.
//compareTo of MyTest is called here.
//Key = 2, Value = 2
//Key = 5, Value = 5
//Key = 10, Value = 20
从输出结果可以看出,MyTest对象在被插入到容器时,该类覆盖实现的compareTo方法被多次调用,而且终的排序结果也是和compareTo方法中的逻辑完全吻合。这里还需要额外指出的是,TreeMap和C++中的map一样,都是不允许重复键的插入,从而保证容器对象中已有键对象的性。这是如何实现的呢?在Java中,当compareTo函数返回0的时候表示两个对象是相等的,我们从上例中可以看出,通常用于JDK对象相等性比较的equals函数并没有被调用,由此可以进一步确认,键对象的相等性比较完全是由compareTo函数来决定的。在此方面,C++中的map容器亦采用了相同的设计理念,只是在细节处理方面不同且更为灵活。我们将在本条目的后面给出更具体的说明。
2)另外一种方式是在构造TreeMap对象时传入Comparator<T>接口的实现类,而该实现类的compare方法将帮助TreeMap对象来确定如何排序容器中的键对象。见如下代码:
public class MyTest {
private int key;
public MyTest(int key) {
this.key = key;
}
public static void main(String[] args) {
TreeMap<MyTest,Integer> tm = new TreeMap<MyTest,Integer>(new Comparator<MyTest>() {
@Override
public int compare(MyTest first,MyTest second) {
System.out.println("compare of Comparator is called here.");
return first.key - second.key;
}
});
tm.put(new MyTest(5), 5);
tm.put(new MyTest(2), 2);
tm.put(new MyTest(10), 10);
for (Entry<MyTest,Integer> e : tm.entrySet())
System.out.println("Key = " + e.getKey().key + ", Value = " + e.getValue());
}
}
//compare of Comparator is called here.
//compare of Comparator is called here.
//Key = 2, Value = 2
//Key = 5, Value = 5
//Key = 10, Value = 10
从上面的输出结果可以看出,Comparator匿名实现类的compare方法确实决定了TreeMap容器中键对象的排序顺序。
现在是时候该展示一下C++中map容器的排序机制了,这里我们先看一下map的类声明形式。
template <class Key, class Type, class Traits = less<Key>, class Allocator=allocator<pair <const Key, Type> > > class map
其中前两个模参分别对应于键对象类型和值对象类型,这一点和Java中TreeMap是一样的。第三个模板参数则在map容器键对象的排序规则上扮演着极为重要的角色。至于后一个参数,主要用于对象的分配机制,由于和本条目关系不大,我们可以直接略过它。
1)从该类的模参声明中可以看到STL的设计者为模参Traits提供了缺省类型参数less<Key>,该类型仍为模板类,其模参类型等同于map中的键类型。这里我们先看一下less<Key>的声明。
1 template<class _Ty>
2 struct less : public binary_function<_Ty, _Ty, bool> {
3 bool operator()(const _Ty& _Left, const _Ty& _Right) const {
4 return (_Left < _Right);
5 }
6 };

sales@spasvo.com