How to find a String inside an Arraylist

Asked

Viewed 1,829 times

1

I have difficulties in using the Arraylist class, more specifically in the search for a String. The point is, my code even works, but when I register more than two books inside Arraylist, at the time of making the query it only "finds" the last book registered, do not find the previous.

That’s my book class:

public final ArrayList<Livro> livros = new ArrayList<>();
// Atributos
private String titulo;
private String autor;
private String editora;
private String consultaLivros;
private int numPags;
private int pagAtual;

public void informacoes() {
    System.out.println("_____________________________________");
    System.out.println("Título: " + this.getTitulo());
    System.out.println("Autor: " + this.getAutor());
    System.out.println("Editora: " + this.getEditora());
    System.out.println("Número de páginas: " + this.getNumPags());
    System.out.println("Página atual: " + this.getPagAtual());
}

public void apresentacao() {
    System.out.println("_____________________________________");
    System.out.println("Título: " + this.getTitulo());
    System.out.println("Número de páginas: " + this.getNumPags());
}

// Getter e Setters
public String getTitulo() {
    return titulo;
}

public void setTitulo(String titulo) {
    this.titulo = titulo;
}

public String getAutor() {
    return autor;
}

public void setAutor(String autor) {
    this.autor = autor;
}

public String getEditora() {
    return editora;
}

public void setEditora(String editora) {
    this.editora = editora;
}

public String getConsultaLivros() {
    return consultaLivros;
}

public void setConsultaLivros(String consultaLivros) {
    this.consultaLivros = consultaLivros;
}

public int getNumPags() {
    return numPags;
}

public void setNumPags(int numPags) {
    this.numPags = numPags;
}

public int getPagAtual() {
    return pagAtual;
}

public void setPagAtual(int pagAtual) {
    this.pagAtual = pagAtual;
}

// Métodos
public void virarPagina(int pagAtual) {
    this.setPagAtual(this.getPagAtual() + 1);
}

public void consultaLivro() {
    System.out.print("Digite o nome do título a ser pesquisado: ");
    Scanner input = new Scanner(System.in);
    this.setConsultaLivros(input.nextLine());

    for (int i = 0; i < livros.size(); i++) {
        if (livros.get(i).getTitulo().contains(this.getConsultaLivros())) {
            livros.get(i).informacoes();
            System.out.println("");
            break;
        } else {
            System.out.println("Título não encontrado!");
            System.out.println("");
            break;
        }
    }
}

This is the main class:

    entrada = new Scanner(System.in);
    Livro book = new Livro();
    int verificarCadastro = 1;
    while (verificarCadastro == 1 || verificarCadastro == 2) {
        System.out.println("Bem vindo a sua biblioteca. ");
        System.out.println("Digite 1 para NOVO livro.");
        System.out.println("Digite 2 para CONSULTAR livro.");
        System.out.println("Digite 0 para SAIR.");
        verificarCadastro = entrada.nextInt();
        System.out.println("");
        switch (verificarCadastro) {
            case 0:
                System.out.println("Você saiu do programa.");
                System.out.println("");
                break;
            case 1:
                System.out.print("Digite o nome do livro: ");
                entrada.nextLine();
                book.setTitulo(entrada.nextLine());

                System.out.print("Digite o nome do Autor: ");

                book.setAutor(entrada.nextLine());

                System.out.print("Digite o nome da editora: ");
                book.setEditora(entrada.nextLine());

                System.out.print("Digite o número de páginas: ");
                book.setNumPags(Integer.parseInt(entrada.nextLine()));

                System.out.print("Digite a página atual: ");
                book.setPagAtual(Integer.parseInt(entrada.nextLine()));
                System.out.println("");
                book.livros.add(book);
                break;
            case 2:
                book.consultaLivro();
                break;
            default:
                System.out.println("Você digitou uma opção inválida.");
                System.out.println("");
                break;
        }
    }
}
  • I’m sure this has been answered before. Does anyone find a duplicate?

  • 1

    public void informacoes() { is not a builder.

  • 1

    Your class Livro has a ArrayList<Livro> - That is, you say that a book has several books. This does not seem to be an appropriate object-oriented modeling.

  • I’m starting object-oriented programming. I don’t know what a proper object-oriented modeling would be, thanks for the help. I’ll give you a closer look.

  • @Victorstafusa then, I had made a builder but I ended up changing my mind, and in the middle of it all I forgot to delete the comment. Thanks for the reminder :)

2 answers

5


The answer from Math has already demonstrated the problem in its method consultaLivro(). But there are still other problems.

Basically, in your class Livro, you have these two fields:

public final ArrayList<Livro> livros = new ArrayList<>();
private String consultaLivros;

This means that each book has several books and that each book has one String book query. This is not an appropriate object-oriented modeling, as the book list does not belong to any book. A String search also does not belong to a book. In addition, the field livros is public, and you should know that it is not good practice to maintain public instance fields.

Besides, you don’t need the field consultaLivros for nothing, and neither the corresponding getter and Setter. See in your method consultaLivro:

this.setConsultaLivros(input.nextLine());

for (int i = 0; i < livros.size(); i++) {
    if (livros.get(i).getTitulo().contains(this.getConsultaLivros())) {

Note that you read a dice (consultaLivros), puts it inside the object and takes that same data from that same object. This then is a fact that once read, has only meaning within this method, and once the method is finished, it loses the sense of existing. Moreover, it would only make sense to store this in the instance (this) if this data were transported somewhere else, which is not the case here because the consultaLivros loses the purpose of existing within the same method in which it is born. Therefore, this should be a local variable, not an object field. So, already counting with the Math changes, your method would look like this:

public void consultaLivro() {
    System.out.print("Digite o nome do título a ser pesquisado: ");
    Scanner input = new Scanner(System.in);
    String consultaLivros = input.nextLine();

    boolean achou = false;
    for (int i = 0; i < livros.size(); i++) {
        if (livros.get(i).getTitulo().contains(consultaLivros)) {
        System.out.println("O livro cadastrado está na posição: " + livros.indexOf(i));
        livros.get(i).informacoes();
        System.out.println("");
        achou = true;
    }
    if (!achou) {
        System.out.println("Título não encontrado!");
        System.out.println("");
    }
}

And the countryside consultaLivros and the corresponding getter and Setter can be deleted.

As I mentioned before, it doesn’t make sense for a book to have several books or a book to belong to another book. In fact, it’s worse than that. In your main class, you have this:

Livro book = new Livro();
// ... várias linhas de código aqui.
book.livros.add(book);

These are the only two places where you create a book or add it to the list of books. This means that:

  • Your system only has a single book (after all, you only urged it once).
  • That the list of books will contain several times the same book.
  • That a book contains itself several times.
  • That a book belongs to itself multiple times.

I mean, this is not gonna do anything that looks like what you want.

This can be solved by creating a class Biblioteca containing a list of books:

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Biblioteca {
    private final List<Livro> livros;

    public Biblioteca() {
        this.livros = new ArrayList<>(10);
    }

    public void adicionarLivro(Livro livro) {
        this.livros.add(livro);
    }

    public void consultarLivro() {
        System.out.print("Digite o nome do título a ser pesquisado: ");
        Scanner input = new Scanner(System.in);
        String consultaLivros = input.nextLine();

        boolean achou = false;
        for (int i = 0; i < livros.size(); i++) {
            if (livros.get(i).getTitulo().contains(consultaLivros)) {
            System.out.println("O livro cadastrado está na posição: " + livros.indexOf(i));
            livros.get(i).informacoes();
            System.out.println("");
            achou = true;
        }
        if (!achou) {
            System.out.println("Título não encontrado!");
            System.out.println("");
        }
    }
}

Also, let’s see your method virarPagina:

    public void virarPagina(int pagAtual) {
        this.setPagAtual(this.getPagAtual() + 1);
    }

Note that the parameter pagAtual is not used.

You see, in your code, the book.setAutor(entrada.nextLine()); is altering the author of the book, instead of being defining the author of the book being registered. This is another problem that tends to lead you to make mistakes that make you constantly change the same book instead of creating new books. Conceptually, when a book is registered, it already contains all the information necessary to be a book and considering that they have been registered correctly, it does not make sense that they are changed. That is, the constructor should already return an object Livro ready for use, not an incomplete skeleton to be repaired after by invoking a bunch of setters.

Another detail is that the methods setPagAtual and virarPagina do not respect the number of pages in the book. You cannot turn the page if you are already in the last.

Abbreviate names (e.g.: pagAtual) is also not good programming practice. Use paginaAtual.

Considering all this, here’s your new class Livro:

public class Livro {

    private String titulo;
    private String autor;
    private String editora;
    private int numeroPaginas;
    private int paginaAtual;

    public Livro(String titulo, String autor, String editora, int numeroPaginas, int paginaAtual) {
        if (numeroPaginas <= 0) throw new IllegalArgumentException();
        if (paginaAtual <= 0 || paginaAtual > numeroPaginas) throw new IllegalArgumentException();
        this.titulo = titulo;
        this.autor = autor;
        this.editora = editora;
        this.numeroPaginas = numeroPaginas;
        this.paginaAtual = paginaAtual;
    }

    public String getTitulo() {
        return titulo;
    }

    public void setTitulo(String titulo) {
        this.titulo = titulo;
    }

    public String getAutor() {
        return autor;
    }

    public void setAutor(String autor) {
        this.autor = autor;
    }

    public String getEditora() {
        return editora;
    }

    public void setEditora(String editora) {
        this.editora = editora;
    }

    public int getNumeroPaginas() {
        return numeroPaginas;
    }

    public void setNumeroPaginas(int numeroPaginas) {
        this.numeroPaginas = numeroPaginas;
    }

    public int getPaginaAtual() {
        return paginaAtual;
    }

    private boolean paginaExiste(int numeroPagina) {
        return numeroPagina >= 1 && numeroPagina <= numeroPaginas;
    }

    public void setPaginaAtual(int novaPaginaAtual) {
        if (!paginaExiste(novaPaginaAtual)) throw new IllegalArgumentException();
        this.paginaAtual = novaPaginaAtual;
    }

    public void virarPagina() {
        if (paginaExiste(paginaAtual + 1)) this.paginaAtual++;
    }

    public void voltarPagina() {
        if (paginaExiste(paginaAtual - 1)) this.paginaAtual--;
    }
}

It is not good programming practice to mix visualization logic (be it System.out.println, desktop screens and layout, HTML, android, etc.) with business logic (which is the one that defines what your system does and how it behaves). The idea is that the same business logic should be able to be expressed and handled independently of what is used to display it and interact with the user, which makes it portable to various environments. However, whenever you use one System.out, one JOptionPane or a piece of HTML within your business logic, you play that premise by land. There are still several other reasons not to mix these things (more on this below).

Therefore, I have withdrawn the methods informacoes() and apresentacao() of your class Livro above. We will remake your class Biblioteca thinking about it:

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class Biblioteca {
    private final List<Livro> livros;

    public Biblioteca() {
        this.livros = new ArrayList<>(10);
    }

    public void adicionarLivro(Livro livro) {
        this.livros.add(livro);
    }

    public Optional<Livro> consultarLivro(String consultaLivros) {
        for (Livro book : livros) {
            if (book.getTitulo().contains(consultaLivros)) return Optional.of(book);
        }
        return Optional.empty();
    }
}

The Optional is an object that may or may not contain another within. If it contains, it means that what was given was found. If not, it is because it was not found. And note that the method consultaLivro cares only to consult the book and return it if found. It is not his responsibility to ask the user what is the book to be consulted or to display this data anywhere. Since this method is decoupled from visualization logic, you won’t get screwed if you want to put the book information in a file instead of in the System.out. Something similar can be argued about the System.in.

Finally, its main classes:

import java.util.Scanner;
import java.util.Optional;

public class CadastroBiblioteca {
    private final Scanner entrada;
    private final Biblioteca biblioteca;

    public CadastroBiblioteca() {
        this.biblioteca = new Biblioteca();
        this.entrada = new Scanner(System.in);
    }

    public void lerLivro() {
        System.out.print("Digite o nome do livro: ");
        String titulo = entrada.nextLine();

        System.out.print("Digite o nome do autor: ");
        String autor = entrada.nextLine();

        System.out.print("Digite o nome da editora: ");
        String editora = entrada.nextLine();

        System.out.print("Digite o número de páginas: ");
        int numeroPaginas = Integer.parseInt(entrada.nextLine());

        System.out.print("Digite a página atual: ");
        int paginaAtual = Integer.parseInt(entrada.nextLine());

        biblioteca.adicionarLivro(new Livro(titulo, autor, editora, numeroPaginas, paginaAtual));
    }

    public void consultarLivro() {
        System.out.print("Digite o nome do título a ser pesquisado: ");
        String consulta = entrada.nextLine();

        Optional<Livro> opt = biblioteca.consultarLivro();

        if (!opt.isPresent()) {
            System.out.println("Título não encontrado!");
            return;
        }

        Livro livro = opt.orElseThrow(AssertionError::new);
        System.out.println("_____________________________________");
        System.out.println("Título: " + livro.getTitulo());
        System.out.println("Autor: " + livro.getAutor());
        System.out.println("Editora: " + livro.getEditora());
        System.out.println("Número de páginas: " + livro.getNumeroPaginas());
        System.out.println("Página atual: " + livro.getPaginaAtual());
    }
}
public class SistemaBiblioteca {

    public static void main(String[] args) {
        CadastroBiblioteca cadastro = new CadastroBiblioteca();
        while (true) {
            System.out.println("Bem vindo a sua biblioteca. ");
            System.out.println("Digite 1 para NOVO livro.");
            System.out.println("Digite 2 para CONSULTAR livro.");
            System.out.println("Digite 0 para SAIR.");
            String verificarCadastro = entrada.nextLine();
            System.out.println("");
            switch (verificarCadastro) {
                case "0":
                    System.out.println("Você saiu do programa.");
                    return;
                case "1":
                    cadastro.lerLivro();
                    break;
                case "2":
                    cadastro.consultarLivro();
                    break;
                default:
                    System.out.println("Você digitou uma opção inválida.");
                    System.out.println("");
                    break;
            }
        }
    }
}

Split in two to separate the implementation menu from the features.

  • 2

    Our Victor, thank you so much for your help. I’m learning how to program OO now and these considerations of yours about my code have really helped. Thank you very much! I am implementing the codes here and trying to understand them, and some concepts so far unknown!

  • 2

    great analysis !

4

In your query you scan the list but stop the loop in the first element being the title of the book found or not when using the breaks within the if and of else

for (int i = 0; i < livros.size(); i++) {
    if (livros.get(i).getTitulo().contains(this.getConsultaLivros())) {
        System.out.println("O livro cadastrado está na posição: " + livros.indexOf(i));
        livros.get(i).informacoes();
        System.out.println("");
        break; //AQUI
    } else {
        System.out.println("Título não encontrado!");
        System.out.println("");
        break; //E AQUI
    }
}

You can take the breaks and let the list be swept through, and the message of "Title not found" be sent off the loop, like this:

boolean achou = false;
for (int i = 0; i < livros.size(); i++) {
    if (livros.get(i).getTitulo().contains(this.getConsultaLivros())) {
        System.out.println("O livro cadastrado está na posição: " + i);
        livros.get(i).informacoes();
        System.out.println("");
        achou = true;
    }
}
if (!achou) {
    System.out.println("Título não encontrado!");
    System.out.println("");
}

See working on on Ideone

  • Guys, I tested the code with the changes and the error persists. Still only find the last book registered.

  • @Math was taking a test to see how many books were registered, if he was updating. I forgot to take :) hehe

Browser other questions tagged

You are not signed in. Login or sign up in order to post.