Во-первых, как прокомментировано , вы не должны расширять 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}]}