1

I have set up an ArrayList of type book for my library application. The current feature I am trying to implement is editing the details of a book. I have a variable called bookID so when I call this method through the ArrayList it will be newBook.get(index).getBookID();. And with this information I would like to check, and do the following things:

  • There exists an element of the array with this ID
  • Update the existing title with a new title

Problems I am being faced with:

  • Looping through to get the index where the ID exists
  • Updating the existing title, and replacing it with a new title

What I have came up with so far:

    // Editing book in ArrayList
public void editBook(){
    System.out.println("==============================");
    // Ensuring array has at least one book
    if(newBook.size() > 0){
        // Get which part, and book the user would like to edits
        System.out.print("Enter Book ID to begin editing: ");
        int bookID = sc.nextInt();
        System.out.println("Press 1 or 2 to edit.");
        System.out.println("1: Edit title");
        System.out.println("2: Edit author");
        System.out.print("Enter option: ");
        int editOption = sc.nextInt();

        // Switch statement which will handle editing book
        switch(editOption){
        case 1: 
            // New title
            System.out.print("Enter new title: ");
            String newTitle = sc.nextLine();
            sc.next();

            // Updates title
            newBook.get(position).setTitle(newTitle);

            // Prints out title
            System.out.println(newBook.get(position).getTitle());

            break; // Edit title

Above code is only partial, and anything below this is irrelevant to the question.

Aidan Donnelly
  • 95
  • 1
  • 10
  • 2
    Use a `Map`, keyed to the `bookId` or you could use Java 8's new `Stream` API and `filter` the `List`, for [example](http://stackoverflow.com/questions/34081193/get-some-value-from-listobject-java/34081295#34081295), but using a `Map` is more efficent – MadProgrammer Dec 08 '15 at 00:51
  • `int editOption = sc.nextInt(); ... String newTitle = sc.nextLine();` -> [Skipping nextLine() after using next(), nextInt() or other nextFoo() methods](https://stackoverflow.com/questions/13102045/skipping-nextline-after-using-next-nextint-or-other-nextfoo-methods) (I didn't read your question but this problem needs correction). – Pshemo Dec 08 '15 at 00:52
  • Sorry, I am unsure what the `Map` does. I am still a first year student. – Aidan Donnelly Dec 08 '15 at 00:52
  • Do you know what a tree data structure is? It's kind of similar, it allows for quicker look up items based on a unique key. See [Collections Trail](http://docs.oracle.com/javase/tutorial/collections/) – MadProgrammer Dec 08 '15 at 00:53
  • 1
    A way you may be more familiar with is creating a method with an int parameter (int bookId). You can use a for/for-each loop that returns the object/index if `newBook.getId() == bookId`, otherwise returns null or -1 upon completion of the loop. `Map`, as pointed out however, is more efficient and it's definitely worth familiarizing yourself with even if you don't yet feel comfortable enough to use it. – Monkeygrinder Dec 08 '15 at 01:15

2 Answers2

1

The Direct Approach...

All this does it loops through the List of Books and compares the bookID entered by the user against the bookID of the book. If a match is found, then the Book reference is maintained in the variable bookToEdit.

If, after the loop is completed, bookToEdit is null then there is no matching Book in the List with the specified ID, otherwise, you now have a reference to the book which needs to be edited

// Get which part, and book the user would like to edits
System.out.print("Enter Book ID to begin editing: ");
int bookID = sc.nextInt();
sc.nextLine();
Book bookToEdit = null;
for (Book book : newBook) {
    if (book.getId() == bookID) {
        bookToEdit = book;
        break;
    }
}
if (bookToEdit != null) {

    System.out.println("Press 1 or 2 to edit.");
    System.out.println("1: Edit title");
    System.out.println("2: Edit author");
    System.out.print("Enter option: ");
    int editOption = sc.nextInt();
    sc.nextLine();

    if (editOption == 1 || editOption == 2) {
        System.out.print("New " + (editOption == 1 ? "title: " : "author: "));
        String value = sc.nextLine();
        switch (editOption) {
            case 1:
                // Update title
                break;
            case 2:
                // Update author
                break;
        }
    } else {
        System.out.println("Invalid edit option");
    }

} else {
    System.out.println("Book with the id of " + bookID + " does not exist");
}

Streams

If you want to do something a little more fancy, you could use...

// Get which part, and book the user would like to edits
System.out.print("Enter Book ID to begin editing: ");
int bookID = sc.nextInt();
sc.nextLine();

List<Book> filtered = newBook.stream().filter((Book t) -> t.getId() == bookID).collect(Collectors.toList());
if (!filtered.isEmpty()) {
    Book bookToEdit = filtered.get(0);

Now, you need to know, this is less efficent then the previous loop, in the fact that it will loop through the entire List of newBook and will return ALL the books which match the bookId (there should realistically only be one)

Map

The most efficient method would be to maintain the Books in a Map, rather then a List, keyed to the bookId. This way, when required, you could simply look up the book by it's id

Map<Integer, Book> newBook = new HashMap<>();
//...
newBook.put(1, new Book(1, "Star Wars", "Somebody"));
newBook.put(2, new Book(2, "Harry Potter", "Somebody else"));
//...

// Get which part, and book the user would like to edits
System.out.print("Enter Book ID to begin editing: ");
int bookID = sc.nextInt();
sc.nextLine();

if (newBook.containsKey(bookID)) {
    Book bookToEdit = newBook.get(bookID);

Conceptually, all this is doing is generating a mapping or relationship between the key and the object, this makes it quicker and simpler to find an object based on the supplied key

Have a look at Collections Trail for more details

MadProgrammer
  • 323,026
  • 21
  • 204
  • 329
0

Please use a Map to solve your problem. You can visit: http://www.tutorialspoint.com/java/java_map_interface.htm.

Here are some example code provided for you:

    //init the map
    Map<String, Book> dataMap = Maps.newHashMap();


    //insert record
    dataMap.put(bookId, book);


    //update record
    Optional<Book> bookOpt = Optional.ofNullable(dataMap.get(bookId));
    bookOpt.ifPresent(book->{
        book.setTitle(newTitle);
    });