我有这个火星人类:
public abstract class Martian implements Cloneable {
int id;
public Martian(int id) {
this.id = id;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public int getId() {
return id;
}
public boolean equals(Object o){
if( o != null);
return this.getId() == ((Martian)o).getId();
}
public abstract void speak();
public String toString(){
return "Martian" + getId();
}
}
和一个MartianManager类:
public class MartianManager {
private ArrayList<Martian> martians;
private ArrayList<Martian> teleporters;
public void addMartian(Martian m) {
martians.add(m);
if(m instanceof GreenMartian)
teleporters.add(m);
}
//public Object clone() {
public Martian getMartianClosestToID(int id) {
}
public void groupSpeak() {
for(Martian m : martians) {
m.speak();
}
}
public void groupTeleport(String dest) {
for (Martian m : martians){
if (m instanceof GreenMartian)
((GreenMartian) m).teleport(dest);
}
}
//public obliterateTeleporters()
//removeMartian(int id)
}
在MartianManager
类中,我有一个方法getMartianClosestToId()
,它返回最接近输入id的id的火星人。我的问题基本上是在循环中使用的最简单的逻辑,或者是他们更简单的方法,例如compareTo
我不知道如果比较甚至可以在类似的情况下工作此
答案 0 :(得分:1)
这不是最简单的,但在很多情况下它会是最快的。
如果你愿意保持你的火星人列表总是按id排序(如果你不经常添加火星人就很容易,你可以在添加火星人时进行排序),你可以这样做:< / p>
Comparator<Martian> compareById = new Comparator<Martian>() {
public int compare(Martian a, Martian b) {
return Integer.compare(a.getId(), b.getId());
}
}
然后,您可以在列表中使用二进制搜索来查找列表中要插入的位置。
int location = Collections.binarySearch(martians, idToGetClosestTo, compareById);
现在,在这一点上,你将会有它应该去的地方,你将有五个选择之一:
这有一个昂贵的前期成本(排序)但是在你排序之后,你可以使用二进制搜索,这是非常便宜的,每次都能非常快速地找到最接近的火星人。
如果您要经常添加,那么我建议将新的火星添加到最后并将您的收藏标记为未排序,然后仅在您要找到它时进行排序。
public Martian getMartianClosestToID(int id) {
if(!martiansAreSorted) Collections.sort(martians,compareById);
int loc = Collections.binarySearch(martians,id,compareById);
if(loc >= 0) return martians.get(loc); // found exact match
// we know loc is negative because it wasn't found - read the docs
loc = -loc;
if(loc == 0) return martians.get(0);
if(loc == martians.size()) return martians.get(loc - 1);
Martian high = martians.get(loc);
Martian low = martians.get(loc - 1);
int highid = high.getId();
int lowid = low.getId();
int highdiff = Math.abs(id - highid);
int lowdiff = Math.abs(id - lowid);
if(highdiff < lowdiff) return high;
return low;
}
答案 1 :(得分:0)
这样的事情应该有效。
这是否正是你想要的取决于一些假设。 ID是唯一的吗?火星人能与自己最接近吗?如果有两个同样接近的火星人怎么办?还是没有其他火星人?我假设'id'参数可能是集合中的ID之一 - 而且你不想要那个。
但最大的问题是:“最接近”是什么意思? “亲密度”的概念通常不适用于ID。
public Martian getMartianClosestToId(int id) {
Martian closest = null;
int leastDist = -1;
for(Martian m : martians) {
int mId = m.getId();
if(mId == id)
continue; // Skip the Martian with the same id.
int d = Math.abs(mId - id);
if(leastDist == -1 || d < leastDist) {
leastDist = d;
closest = m;
}
}
return closest;
}
我没有编译/测试过这个 - 你可能需要修复拼写错误。
答案 2 :(得分:0)
我认为这比其他答案简单(OP要求“最简单的逻辑”):
public Martian getMartianClosestToID(int id)
{
if (martians == null || martians.isEmpty())
return null;
Martian result = martians.get(0);
for (Martian m : martians)
if (Math.abs(id - m.getId()) < Math.abs(id - result.getId()))
result = m;
return result
}