我在未排序的链表和排序的链表中实现了remove(Object o)方法。这两个类都扩展了AbstractLinkedList(代码重用)
这是我在未排序链表中删除(对象o)的代码
@Override
public void remove(E value) {
if(front != null) {
if(front.data.equals(value)) {
front = front.next;
} else {
ListNode<E> current = front;
boolean hasRemovedElement = false;
while(current.next != null && !hasRemovedElement) {
if(current.next.data.equals(value)) {
current.next = current.next.next;
hasRemovedElement = true;
}
current = current.next;
}
}
}
}
我的代码是在排序链表中删除(对象o)
public void remove(E value) {
if(front != null) {
ListNode<E> current = front;
if(front.data.equals(value)) {
front = front.next;
} else {
boolean hasRemovedElement = false;
while(current.next != null && !hasRemovedElement
&& current.next.data.compareTo(value) >= 0) {
if(current.next.data.equals(value)) {
current.next = current.next.next;
hasRemovedElement = true;
}
current = current.next;
}
}
}
我立刻注意到的是我的两种方法中的代码几乎完全相同。排序链接列表中的remove(Object o)只有一个条件检查,说明如果下一个元素小于您尝试删除的值,则您尝试删除的元素无法在列表中找到。我利用代码重用做的是在AbstractLinkedList中实现两个列表都可以调用的重载版本,即
@Override
protected void remove(E value, E toCheckAgainst) {
if(front != null) {
ListNode<E> current = front;
if(front.data.equals(value)) {
front = front.next;
} else {
boolean hasRemovedElement = false;
while(current.next != null && !hasRemovedElement
&& current.next.data.compareTo(toCheckAgainst) >= 0) {
if(current.next.data.equals(value)) {
current.next = current.next.next;
hasRemovedElement = true;
}
current = current.next;
}
}
}
在未分类的链表中
@Override
public void remove(E value) {
remove(value, CHECKER)
}
但我的问题是我应该如何在未排序的链表中创建这个CHECKER?就排序链表而言,此检查器可能只是值。如果您的值小于检查器(已排序),则检查器的角色基本上是停止迭代。我可以使检查器对未排序的链表没有任何影响有什么价值?我尝试使用像MIN POSSIBLE = -9999999之类的int,但你不能将int与泛型进行比较。或者它在设计方面更好,只是在两个类中都有相同的实现。
答案 0 :(得分:0)
我建议将这些方法保留原样。代码重用应该与可读性等进行权衡。
但是假设你想要这样做,我会使用一种测试程序(或者在Java 8中,Predicate
)。你在超类中声明了这样的接口:
protected interface Tester<E> {
public boolean test(E testObj);
}
然后你的一般删除方法是:
protected void remove(E value, Tester<E> extraCondition) {
if(front != null) {
ListNode<E> current = front;
if(front.data.equals(value)) {
front = front.next;
} else {
boolean hasRemovedElement = false;
while(current.next != null && !hasRemovedElement
&& extraCondition.test(current.next.data) {
if(current.next.data.equals(value)) {
current.next = current.next.next;
hasRemovedElement = true;
}
current = current.next;
}
}
}
}
然后在未分类的列表中,您有:
@Override
public void remove(final E value) {
remove(value, new Tester<E>() {
public boolean test(E testObj) {
return true;
}
});
}
在您的排序列表中:
public void remove(final E value) {
remove(value, new Tester<E>() {
public boolean test(E testObj) {
return testObj.compareTo(value) >= 0;
}
});
}
因此,在未排序的列表中,您传递的条件始终返回true,并且在排序列表中,您传递的条件是基于与值的比较返回true。
你想要测试null然后才进行比较会有效,但是:
一般情况下,不要在超类中放置仅与您当前可以想到的子类相关的专门行为,只是为了在子类中保存一些编码。