在Java中向单链表添加元素

在Java中向单链表添加元素,java,data-structures,singly-linked-list,Java,Data Structures,Singly Linked List,我正在用Java实现一个单链表。我不喜欢这段代码的地方是每次添加元素时都需要检查if(head.next==null)。但在添加第一个元素时,该条件只满足一次 有没有一种方法可以在没有此类条件的情况下实现单链接的非循环列表 package sample; import java.util.Iterator; import java.util.NoSuchElementException; public class SinglyLinkedList<T> implements It

我正在用Java实现一个单链表。我不喜欢这段代码的地方是每次添加元素时都需要检查
if(head.next==null)
。但在添加第一个元素时,该条件只满足一次

有没有一种方法可以在没有此类条件的情况下实现单链接的非循环列表

package sample;

import java.util.Iterator;
import java.util.NoSuchElementException;

public class SinglyLinkedList<T> implements Iterable<T> {

    private Node<T> head = new Node<T>(null);
    private Node<T> last = null;

    public SinglyLinkedList(T... elements) {
        addAll(elements);
    }

    public void add(T element) {
        if (head.next == null) {
            head.next = new Node<T>(element);
            last = head.next;
        } else {
            Node<T> newNode = new Node<T>(element);
            last.next = newNode;
            last = last.next;
        }
    }

    public void addAll(T... elements) {
        for (T element : elements) {
            add(element);
        }
    }

    @Override
    public String toString() {
        Iterator<T> iterator = iterator();
        if (!iterator.hasNext()) {
            return "[]";
        }
        StringBuilder builder = new StringBuilder();
        builder.append("[");
        while (iterator.hasNext()) {
            T element = iterator.next();
            builder.append(element);
            if (!iterator.hasNext()) {
                return builder.append("]").toString();
            }
            builder.append(", ");
        }
        return builder.toString();
    }

    @Override
    public Iterator<T> iterator() {
        return new Iterator<T>() {

            Node<T> current = head;

            @Override
            public boolean hasNext() {
                return current.next != null;
            }

            @Override
            public T next() {
                if (!hasNext()) {
                    throw new NoSuchElementException();
                }
                Node<T> temp = current;
                current = current.next;
                return temp.next.element;
            }

        };
    }

    private static class Node<T> {

        private Node<T> next;
        private T element;

        Node(T element) {
            this.element = element;
        }

        @Override
        public String toString() {
            return element.toString();
        }
    }
}
包装样品;
导入java.util.Iterator;
导入java.util.NoSuchElementException;
公共类SingleLinkedList实现Iterable{
私有节点头=新节点(空);
私有节点last=null;
公共单链接列表(T…元素){
addAll(元素);
}
公共无效添加(T元素){
if(head.next==null){
head.next=新节点(元素);
last=head.next;
}否则{
节点newNode=新节点(元素);
last.next=newNode;
last=last.next;
}
}
公共void addAll(T…元素){
对于(T元素:元素){
添加(元素);
}
}
@凌驾
公共字符串toString(){
迭代器迭代器=迭代器();
如果(!iterator.hasNext()){
返回“[]”;
}
StringBuilder=新的StringBuilder();
生成器。追加(“[”);
while(iterator.hasNext()){
T元素=迭代器.next();
builder.append(元素);
如果(!iterator.hasNext()){
返回builder.append(“]”).toString();
}
生成器。追加(“,”);
}
返回builder.toString();
}
@凌驾
公共迭代器迭代器(){
返回新的迭代器(){
节点电流=头;
@凌驾
公共布尔hasNext(){
返回current.next!=null;
}
@凌驾
公共交通工具{
如果(!hasNext()){
抛出新的NoTouchElementException();
}
节点温度=电流;
当前=当前。下一步;
返回下一个元素的温度;
}
};
}
私有静态类节点{
私有节点下一步;
私有T元素;
节点(T元素){
this.element=元素;
}
@凌驾
公共字符串toString(){
返回元素.toString();
}
}
}

在许多情况下,“良好的OO设计”允许您不进行if/else检查;大多数情况下,使用某种形式的多态性

意思是:不要询问某个对象关于某个属性的信息,然后在客户机代码中对此做出决定,而是以某种方式确保客户机代码可以简单地调用其他对象上的方法。然后,“如果”在最初生成“其他对象”并将其提供给客户端代码的代码中被“隐藏”。(你可以找到一些很好的例子来说明这一点)

但是,我认为在这种情况下,这显然是过火了

要点是:从可读性的角度来看,一次检查确实没有什么坏处(也许你可以将东西重构成更多的方法)。和性能。。。也没关系。如果您的代码被频繁调用,那么不管怎样,JIT都会启动,并且可能会创建在大多数情况下直接采用正确分支的代码


因此:这是一个很好的实现;我想你不必担心这件事,如果你去看看的话

在许多情况下,“良好的OO设计”允许您不进行if/else检查;大多数情况下,使用某种形式的多态性

意思是:不要询问某个对象关于某个属性的信息,然后在客户机代码中对此做出决定,而是以某种方式确保客户机代码可以简单地调用其他对象上的方法。然后,“如果”在最初生成“其他对象”并将其提供给客户端代码的代码中被“隐藏”。(你可以找到一些很好的例子来说明这一点)

但是,我认为在这种情况下,这显然是过火了

要点是:从可读性的角度来看,一次检查确实没有什么坏处(也许你可以将东西重构成更多的方法)。和性能。。。也没关系。如果您的代码被频繁调用,那么不管怎样,JIT都会启动,并且可能会创建在大多数情况下直接采用正确分支的代码


因此:这是一个很好的实现;我想你不必担心这件事,如果你去看看的话

您可以初始化最后一个指向头部,然后您的if是冗余的:

private Node<T> head = new Node<T>(null);
private Node<T> last = head;

public void add(T element) {
        Node<T> newNode = new Node<T>(element);
        last.next = newNode;
        last = last.next;
}
私有节点头=新节点(空);
私有节点last=head;
公共无效添加(T元素){
节点newNode=新节点(元素);
last.next=newNode;
last=last.next;
}

您可以初始化最后一个指向头部,然后您的if是多余的:

private Node<T> head = new Node<T>(null);
private Node<T> last = head;

public void add(T element) {
        Node<T> newNode = new Node<T>(element);
        last.next = newNode;
        last = last.next;
}
私有节点头=新节点(空);
私有节点last=head;
公共无效添加(T元素){
节点newNode=新节点(元素);
last.next=newNode;
last=last.next;
}

为什么需要
最后一个
对象?@marounnaroun,因为我需要将元素附加到列表中。实际上,方法
add
应该被称为
addLast
@marounnaroun,你认为
last
是多余的吗?我看到了一些示例,它们只有head指针,并在列表上迭代以在末尾添加一个项。因此,加法需要O(n),而插入到单链表则需要O(1)。另请参见为什么需要
last
对象?@marounnaroun,因为我需要将元素附加到列表中。实际上,方法
add
应该被称为
addLast
@marounnaroun,你认为
last
是多余的吗?我看到了一些示例,它们只有head指针,并在列表上迭代以在末尾添加一个项。因此,添加将