[英]How to remove ONE of the duplicates in an ArrayList in Java
我有一本 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));
}
}
}
一种解决方案可能是检查 ArrayList 中的最后一个索引。 您可以使用 ArrayList.size() 查看 ArrayList 的大小。 所以例如
int size = ArrayList.size();
然后删除最后一个索引。
您用于存储书籍的数据结构是字符串的 hashmap 和 arraylist。 假设字符串为 book Name 和 arrayList 包含要从中删除最后一本书的同一本书的多个书籍对象
ArrayLiat<Book> booksForName = books.get(bookName);
现在要删除此列表的最后一个元素,您只需要做
booksForName.removes(books.size()-1);
这可以简单地在一行中完成,但代码会。 如果您在几周后尝试阅读,就会变得凌乱且不容易理解:P
首先, 正如评论的那样,您不应该扩展HashMap
。 另外,我看不到您如何将Library
用作Map
。
您在标题中使用“重复”一词具有误导性,因为我们不处理相同数据的重复。 相反,显然您想跟踪一本书的多个副本。
您需要仔细考虑问题域以得出正确的数据结构。 一本书是一个概念(和一块知识产权),具有标题、作者、标识符(ISBN 等)、分类(例如杜威十进制数)等。 一本书的单个物理副本是另一回事。 副本的属性包括由图书管理员标记在每个副本上的标识符,以及图书管理员记录的其状况。 在我们的数据 model 中,我们将跟踪BookCopy
对象作为与父Book
object 相关的子对象。
您希望借阅方法“删除此列表的最后一个”必须意味着您希望按照 LIFO 政策借出我们的书籍:后进先出。 不要使用ArrayList
作为您的集合,而是使用用于此目的的接口的实现: Deque
。 ArrayDeque
对于您的目的可能是一个很好的实现。
实际上, Deque
有点令人困惑,因为它可以以不同的方式使用。 对于 LIFO(后进先出)行为,请调用:
至于向您的地图添加项目,您的books
和lenders
地图就是所谓的多地图。 “多”是指每个键的多个值,而不是每个键的单个值。
Java 现在通过添加到 Java 8 的computeIfAbsent
功能内置了对多图的支持。
以这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
(标题),值是BookCopy
对象的Deque
。
Map < String , Deque < BookCopy > > copiesOnHand = new HashMap <>();
如上所述,除了BookCopy
class 之外,您确实应该拥有Book
class。 如果是这样,将使用Book
object 而不仅仅是标题String
。
Map < Book , Deque < BookCopy > > copiesOnHand = new HashMap <>();
但是为了在这个简短的演示中简单起见,我们将坚持使用String
标题来表示这本书。
首先,我们将书籍副本添加到 map。 computeIfAbsent
行首先检查您指定的键是否在 map 中具有非空值的条目。 如果不是,则实例化并添加该值(一个空的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.
借出意味着我们删除并返回双端队列中的最后一项。
// 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 | 条件=服务},BookCopy {uuid=61f036b5-da62-41fe-a765-f76bc31eebcb | 条件=原始 }]}
借书本ID:731010a2-623a-4200-963a-9ce18f4fe988
CopyOnHand = {Java 并发实践=[BookCopy{ uuid=61f036b5-da62-41fe-a765-f76bc31eebcb | 条件=原始 }]}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.