Как удалить ОДИН из дубликатов в ArrayList в Java - PullRequest
0 голосов
/ 02 мая 2020

У меня есть ArrayList, заполненный несколькими одинаковыми книгами. Теперь мне нужно иметь возможность реализовать метод lendBook (String bookName, String lenderName), который удаляет последний из этого списка. Если я использую books.get(bookName).remove(book), ничего не происходит. Если я использую books.get(bookName).remove(books.get(bookName).get(books.get(bookName).size()-1)), он удаляет весь ArrayList. Заранее спасибо за помощь.

public class Library extends HashMap {

    public Map<String, ArrayList<Book>> books;
    protected Map<String, Lender> lenders;

    public Library() {
        this.books = new HashMap<String, ArrayList<Book>>();
        this.lenders = new HashMap<String, Lender>();
    }


    public void addBook (String bookName){
        String key = bookName;
        if (books.containsKey(key)){
           books.get(key).add(new Book(bookName));
        } else {
            books.put(bookName, new ArrayList<Book>());
            books.get(key).add(new Book(bookName));
        }
    }

    public void addLender (String lenderName) throws java.lang.IllegalStateException {
        String key = lenderName;
        if (lenders.containsKey(key)){
            throw new java.lang.IllegalStateException(lenderName);
        } else {
            lenders.put(lenderName, new Lender(lenderName));
        }
    }
}

Ответы [ 3 ]

0 голосов
/ 02 мая 2020

Структура данных, которую вы используете для хранения книг, представляет собой хэш-карту String и arraylist. Предполагая, что строкой является book Name и arrayList, содержащий несколько объектов книги одной и той же книги, из которой вы хотите удалить последнюю книгу

ArrayLiat<Book> booksForName = books.get(bookName);

Теперь, чтобы удалить последний элемент этого списка, вам просто нужно сделать

booksForName.removes(books.size()-1);

Это можно сделать в одну строку, но код будет. быть грязным и не так легко понять, если вы попробуете читать через несколько недель: P

0 голосов
/ 04 мая 2020

Во-первых, как прокомментировано , вы не должны расширять HashMap. Кроме того, я не вижу, как вы использовали Library как Map.

Использование вами в названии слова «дубликаты» вводит в заблуждение, поскольку мы не имеем дело с дубликатами идентичных данных. Вместо этого, очевидно, вы хотите отслеживать несколько копий книги.

Вам необходимо продумать проблемную область, чтобы прийти к правильной структуре данных. Книга представляет собой концепцию (и часть интеллектуальной собственности) с названием, автором (ами), идентификатором (ISBN et c.), Классификацией (например, десятичным числом Дьюи). , и так далее. Индивидуальные физические копии книги - это нечто другое. Атрибуты копии включают в себя идентификатор, помеченный на каждом из них библиотекарем, и его состояние, отмеченное библиотекарем. В нашей модели данных мы будем отслеживать объекты BookCopy как дочерние объекты, связанные с родительским объектом Book.

Ваше желание, чтобы метод кредитования «удалял последний из этого списка», должно означать, что вы хотите одолжить наши книги в соответствии с политикой LIFO: последний входит первым - выходит первым. Вместо использования ArrayList в качестве своей коллекции используйте реализацию интерфейса, предназначенную для этой цели: Deque. ArrayDeque может быть хорошей реализацией для ваших целей.

На самом деле, Deque немного сбивает с толку, поскольку его можно использовать по-разному. Для поведения LIFO (Last-in, First-out) звоните:

Что касается добавления элементов на ваши карты, ваши карты books и lenders - это то, что известно как multimap . «Мульти» относится к нескольким значениям на ключ, а не к одному значению на ключ.

Java теперь имеет встроенную поддержку мультикарт с помощью функции computeIfAbsent, добавленной к Java 8.

Возьмем, к примеру, этот класс BookCopy. Мы используем enum Condition для библиотекаря, чтобы записать физическое состояние каждой копии книги. Мы используем значение UUID в качестве идентификатора, который будет проставлен на каждой книге библиотекарем.

package work.basil.example;

import java.util.Objects;
import java.util.UUID;

public class BookCopy
{
    public enum Condition
    { PRISTINE, GOOD, SERVICABLE, DELAPIDATED }

    ;

    // Member fields
    private UUID uuid;
    private Condition condition;

    // Constructor
    public BookCopy ( UUID uuid , Condition condition )
    {
        this.uuid = Objects.requireNonNull( uuid );
        this.condition = Objects.requireNonNull( condition );
    }

    // Accessors

    public UUID getUuid ( ) { return this.uuid; }

    public Condition getCondition ( ) { return this.condition; }

    public void setCondition ( Condition condition ) { this.condition = condition; }

    // Object

    @Override
    public boolean equals ( Object o )
    {
        if ( this == o ) return true;
        if ( o == null || getClass() != o.getClass() ) return false;
        BookCopy bookCopy = ( BookCopy ) o;
        return uuid.equals( bookCopy.uuid );
    }

    @Override
    public int hashCode ( )
    {
        return Objects.hash( uuid );
    }

    @Override
    public String toString ( )
    {
        return "BookCopy{ " +
                "uuid=" + uuid +
                " | condition=" + condition +
                " }";
    }
}

Очевидно, вы хотите отследить, какие копии доступны в библиотеке для кредитования. Для каждой книги нам нужно Deque, содержащее копии, доступные для займа. Если мы будем отслеживать каждую книгу по ее названию как String, у нас будет Map, где ключом будет String (заголовок), а значением будет Deque из BookCopy объектов.

Map < String , Deque < BookCopy > > copiesOnHand = new HashMap <>();

Как упоминалось выше, у вас действительно должен быть класс Book в дополнение к классу BookCopy. Если это так, будет использоваться объект Book, а не просто заголовок String.

Map < Book , Deque < BookCopy > > copiesOnHand = new HashMap <>();

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

Сначала мы добавляем копии книг на эту карту. Строка computeIfAbsent сначала проверяет, есть ли в указанном вами ключе запись на карте с ненулевым значением. Если нет, то значение (пустое ArrayDeque) создается и добавляется.

// Two copies of this book to lend.
String title = "Java Concurrency in Practice";

BookCopy bookCopy1 = new BookCopy( UUID.fromString( "61f036b5-da62-41fe-a765-f76bc31eebcb" ) , BookCopy.Condition.PRISTINE );
copiesOnHand.computeIfAbsent(
        title ,                                // key.
        ( String key ) -> new ArrayDeque <>()
)
        .addFirst( bookCopy1 );                      // value.

BookCopy bookCopy2 = new BookCopy( UUID.fromString( "731010a2-623a-4200-963a-9ce18f4fe988" ) , BookCopy.Condition.SERVICABLE );
copiesOnHand.computeIfAbsent(
        title ,                                // key.
        ( String key ) -> new ArrayDeque <>()
)
        .addFirst( bookCopy2 );                      // value.

Кредитование означает, что мы удаляем и возвращаем последний элемент в deque.

// Debug: See our current inventory.
System.out.println( "copiesOnHand = " + copiesOnHand );

// Lend a book.
BookCopy copyToLend = copiesOnHand.computeIfAbsent(
        title ,                                // key.
        ( String key ) -> new ArrayDeque <>()
)
        .removeFirst();
if ( Objects.nonNull( copyToLend ) )
{
    System.out.println( "Lending book copy ID: " + copyToLend.getUuid() );
} else
{
    System.out.println( "Sorry, no copies of that book available to lend. " );
}

// Debug: Review our inventory after lending.
System.out.println( "copiesOnHand = " + copiesOnHand );

При запуске.

copyOnHand = {Java Параллелизм на практике = [BookCopy {uuid = 731010a2-623a-4200-963a-9ce18f4fe988 | condition = SERVICABLE}, BookCopy {uuid = 61f036b5-da62-41fe-a765-f76bc31eebcb | condition = PRISTINE}]}

Идентификатор копии кредитной книги: 731010a2-623a-4200-963a-9ce18f4fe988

copyOnHand = {Java Практический параллелизм = [BookCopy {uuid = 61f036b5-da62 -41fe-a765-f76bc31eebcb | condition = PRISTINE}]}

0 голосов
/ 02 мая 2020

Одним из решений может быть проверка последнего индекса в ArrayList. Вы можете увидеть размер ArrayList с ArrayList.size (). Например,

int size = ArrayList.size();

Затем удалите последний индекс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...