Как добавить элемент в конце структуры списка в Java? - PullRequest
0 голосов
/ 29 мая 2019

Я пытаюсь написать функцию для добавления нового элемента в конец моего списка. Но я не знаю, как мой метод всегда добавляет новый элемент в первый индекс списка.

У меня есть 2 класса с именами Waypoint и TourElement. Путевая точка содержит метод для обработки точек в связанном списке. TourElment содержит путевую точку и следующую.

Waypoint.java

public class Waypoint {
    int x  ;
    int y  ;
    public int getX()
    {
        return this.x;
    }
    public int getY()
    {
        return this.y;
    }
    public void setXY(int x, int y)
    {
        this.x = x;
        this.y = y;
    }
}

TourElement.java

 public class TourElement {
     private Waypoint points;
     private TourElement next;
     public void setWaypoint( Waypoint points)
     {
         this.points = points; 
     }
     public void setTourElement(TourElement next)
     {
         this.next = next;
     }
     Waypoint getWaypoint()
     {
         return this.points;
     }

     TourElement getNext()
     {
         return this.next;
     }

     //+ method below
}

метод добавляет новый TourElement в список. Почему всегда добавлять TourElement в первый индекс списка?

public TourElement append(Waypoint waypoint)
{
    TourElement newTourElement = new TourElement();
    TourElement current = this;
    while(current.next != null)
    {
        current = current.next;
    }
    newTourElement.setWaypoint(waypoint);
    current.next = newTourElement;
    return newTourElement;
}

Вот мой тестовый пример: // создаем список элементов:

private TourElement createElementList(int[][] waypoints){
        assert waypoints.length > 0;
        TourElement elem = new TourElement();
        int lastIndex = waypoints.length-1;
        Waypoint wp = createWaypoint(waypoints[lastIndex][0], waypoints[lastIndex][1]);
        elem.setWaypoint(wp);
        for (int i = lastIndex-1; i >= 0 ; i--) {
            wp = createWaypoint(waypoints[i][0], waypoints[i][1]);
            elem = elem.addStart(wp);
        }
        return elem;
    }

// создать путевую точку:

private Waypoint createWaypoint(int x, int y) {
        Waypoint wp = new Waypoint();
        wp.setXY(x, y);
        return wp;
    }

// добавить Start

public   TourElement addStart(Waypoint wp) {
     TourElement newTourElement = new TourElement();
     newTourElement.setWaypoint(wp);
     newTourElement.setTourElement(this);
     return newTourElement;   
    }  



 public void testAppend() {
        TourElement elem = createElementList(new int[][] {{2, 2}});
        elem = elem.append(createWaypoint(3, 3));
        assertArrayEquals(new int[] {2, 2}, elem.getWaypoint().toArray());
        assertArrayEquals(new int[] {3, 3}, elem.getNext().getWaypoint().toArray());
        assertNull(elem.getNext().getNext());
    }

public void testAppend_AfterTwo() {
    TourElement elem = createElementList(new int[][] {{1, 1}, {2, 2}});
    elem = elem.append(createWaypoint(3, 3));
    assertArrayEquals(new int[] {1, 1}, elem.getWaypoint().toArray());
    assertArrayEquals(new int[] {2, 2}, elem.getNext().getWaypoint().toArray());
    assertArrayEquals(new int[] {3, 3}, elem.getNext().getNext().getWaypoint().toArray());
    assertNull(elem.getNext().getNext().getNext());
}

Я ожидаю, что результат будет выглядеть так:

Контрольный пример 1 : {2,2} => {3,3}

Контрольный пример 2 : {1,1} => {2,2} => {3,3}

Но мой фактический результат:

Контрольный пример 1 : {3, 3} => {2,2}

Контрольный пример 2 : {3,3} => {1,1} => {2,2}

1 Ответ

0 голосов
/ 29 мая 2019

Вы обновляете "elem" в строке elem = elem.append(createWaypoint(3, 3));.

Так что мне интересно, как ваши тесты в любом случае возвращают полный список? Я ожидаю, что «фактический результат» будет только «{3,3}».

Чтобы решить эту проблему, тест НЕ должен вообще изменять переменную elem, после того как она инициализирована на первом месте:

 public void testAppend() {
        // add "final" to prevent accidentially changes of references
        final TourElement elem = createElementList(new int[][] {{2, 2}});

        // DO NOT CHANGE "elem"!
        // elem = elem.append(createWaypoint(3, 3));
        // instead keep the reference to the first elem:
        elem.append(createWaypoint(3, 3));

        assertArrayEquals(new int[] {2, 2}, elem.getWaypoint().toArray());
        assertArrayEquals(new int[] {3, 3}, elem.getNext().getWaypoint().toArray());
        assertNull(elem.getNext().getNext());
    }

Кстати: ваш код может быть НАМНОГО понятнее, если вы дадите конструктору "Waypoint" "Waypoint(x, y)", сделаете поля x и y окончательными, удалите setXY() и добавите toString().

public class Waypoint {
    final int x;
    final int y;
    public WayPoint(int x, int y) {
        this.x = x;
        this.y = y;
    }
    public int getX() { ... }
    public int getY() { ... }

    @Override
    public String toString() {
        return String.format("{%d,%d}", x, y);
    }
}

Вашему TourElement может потребоваться метод Collection<Waypoint> waypoints(), который возвращает последующие Waypoint объекты (облегчает тестирование).

public Collection<Waypoint> waypoints() {
    Collection<Waypoint> res = new java.util.ArrayList<>();
    TourElement currTE = this;
    while (currTE.next()!=null) {
        res.add(currTE.getWaypoint());
        currTE = currTE.next();
    }
    return res;
}

Чтобы затем распечатать список Waypoint, вы просто делаете

    org.apache.commons.lang.StringUtils.join(elem.waypoints(), ", ");
...