Java 链表循环潜在异常
下面是检测链表是否包含循环的代码:Java 链表循环潜在异常,java,linked-list,nodes,Java,Linked List,Nodes,下面是检测链表是否包含循环的代码: public static boolean containsCycle(LinkedListNode firstNode) { // start both runners at the beginning LinkedListNode slowRunner = firstNode; LinkedListNode fastRunner = firstNode; // until we hit the end of the list while (fast
public static boolean containsCycle(LinkedListNode firstNode) {
// start both runners at the beginning
LinkedListNode slowRunner = firstNode;
LinkedListNode fastRunner = firstNode;
// until we hit the end of the list
while (fastRunner != null && fastRunner.next != null) {
slowRunner = slowRunner.next;
fastRunner = fastRunner.next.next;
// case: fastRunner is about to "lap" slowRunner
if (fastRunner == slowRunner) {
return true;
}
}
// case: fastRunner hit the end of the list
return false;
while循环的条件不应该是fastRunner!=null&&fastRunner.next.next!=无效的对于当前代码,fastRunner可能是链接列表中的最后一个节点,因此一旦进入while循环,最后一个节点的下一个节点将导致异常
使用当前代码,fastRunner可以是链接列表中的最后一个节点
fastRunner
不能是链接列表中的最后一个节点,因为您的while
循环
while (fastRunner != null && fastRunner.next != null) {
检查fastRunner
是否不是最后一个元素(因为fastRunner.next==null
意味着fastRunner
是最后一个元素)。这个作业在你的循环中
fastRunner = fastRunner.next.next;
当然可以将
fastRunner
设置为null
,但您没有使用它来执行任何会导致null指针异常的操作,并且while
循环的下一次迭代将退出(因为现在fastRunner==null
)只要线程安全不是问题,此算法肯定是正确的。
换句话说,如果在该方法运行时另一个线程中的代码更改了列表,那么它肯定会产生错误的结果或NullPointerException
但是,如果您的代码是单线程的,NullPointerException
就永远不会发生。要使此代码抛出一个NullPointerException
,必须有一个
运算符,其左侧有一个空值。尽管还有其他类型的代码可以抛出NullPointerException
,例如自动取消装箱空值,并在for each循环中使用空参数;你没有这些
<> p>因此,如果看到这个代码可以抛出while(fastRunner!=null&&fastRunner.next!=null){
-这不会导致NullPointerException
,因为只有在fastRunner
由于短路评估而不为null时,才会检查此代码slowRunner=slowRunner.next;
-这永远不会导致NullPointerException
,因为slowRunner
获取的每个值都已经被fastRunner
或fastRunner.next
获取。因此,如果slowRunner
为null,您就已经获得了fastRunner=fastRunner.next.next;
-这不会导致NullPointerException
,因为您已经检查了fastRunner
是否为空fastRunner=fastRunner.next.next;
-这不会导致NullPointerException
,因为您已经检查了fastRunner.next
是否为空NullPointerException
的点,除非在代码执行时第二个线程更改了列表