Как мне объединить значения из всех объектов класса в Java?

#java #object #foreach #accumulate

#java #объект #foreach #накапливать

Вопрос:

Я пытаюсь извлечь определенные значения из нескольких объектов одного и того же класса. Я использовал цикл for each для перебора каждого объекта и хотел бы создать агрегированный итог, представляющий рейтинг и стоимость элемента из объектов.

Для каждого цикла в моем родительском классе:

 for (Song songObj : Song.returnSongs()) {
    totalSongCost  = Double.parseDouble(songObj.getPrice());
    totalSongRating  = Integer.parseInt(songObj.getRating());
}
  

Дочерний класс ArrayList предназначен для хранения объектов:

 private int rating;
private String title;
private double price;
private boolean favorite;
private static int counter = 0;
private static ArrayList songArray = new ArrayList();

/**
 * Constructor for objects of class Song
 */
public Song()
{
    // initialise instance variables
    rating = 0;
    title = "";
    price = 0.0;
    counter  ;
    songArray.add(this);
}
public static ArrayList returnSongs() {
    return songArray;
}
  

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

Комментарии:

1. Вероятно, у вас должен быть другой класс, например «Album», который содержит список композиций, потому что ваша текущая реализация не будет работать. Вы не можете добавить объект, содержащий список (например, песню), в список (который находится в песне).

2. @BenjaminLowry Объект не содержит списка, потому что он static и, следовательно, не принадлежит какому-либо объекту.

3. @ajb Ах да, мой плохой, не видел, что он был статическим.

Ответ №1:

Если вы когда-либо читали документы, вы знаете, что ArrayList это на самом деле универсальный класс. Это означает, что вы можете указать ArrayList тип.

Тип материала, который может хранить список массивов, зависит от того, какой тип вы ему присвоили. Но если вы не задаете ему никакого типа, он сохраняет Object s! Здесь,

 for (Song songObj : Song.returnSongs()) {
  

вы хотите получить Song объекты из списка Object объектов массива, что не имеет смысла для компилятора. В результате появляется ошибка.

Решение этой проблемы, конечно, заключается в том, чтобы присвоить списку массивов тип, чтобы он знал, какой тип он должен хранить.

Измените это

 private static ArrayList songArray = new ArrayList();
  

к этому:

 private static ArrayList<Song> songArray = new ArrayList<>();
  

и измените это:

 public static ArrayList returnSongs() {
  

к этому:

 public static ArrayList<Song> returnSongs() {
  

Комментарии:

1. По какой-то причине, когда я делаю это, я могу получить доступ только к самому последнему объекту, а не ко всем объектам класса, почему это?

2. Пожалуйста, убедитесь, что songArray это объявлено static . @user6828298

Ответ №2:

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

 private static ArrayList songArray = new ArrayList();
  

к этому:

 private static ArrayList<Song> songArray = new ArrayList<Song>();
  

Тогда класс ArrayList поймет, что вы работаете с экземплярами Song .

Редактировать: как указал Джим Гаррисон, ваш returnSongs() метод также следует изменить, чтобы указать тип класса таким же образом.

 public static ArrayList<Song> returnSongs() { ...
  

Комментарии:

1. Не забудьте также изменить public static ArrayList returnSongs() на public static ArrayList<Song> returnSongs() и общий тип в точке, где returnSongs() вызывается.

Ответ №3:

Немного необычно Song , когда класс отвечает за отслеживание всех композиций в приложении. Это, по-видимому, выходит за рамки ответственности этого класса и, возможно, лучше подходит для обработки в другом классе, либо в вашем родительском классе, либо в новом типе, специально определенном.

Кроме того, будьте осторожны при использовании типов, таких как List и ArrayList . Как предупредит вас ваш компилятор, для этого требуются параметры типа в угловых скобках (т.Е. List<Type> ). Вы должны выработать привычку обращаться ко всем предупреждениям компилятора и всегда указывать параметры типа для универсальных типов, таких как List . В тех случаях, когда вы неправильно определяете свои типы, по умолчанию все становится Object равным , что приводит к проблеме, с которой вы столкнулись здесь.

Ниже приведен пример того, как это может выглядеть, реструктурированный, чтобы сохранить Song класс исключительно для атрибутов самой песни:

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

public class Parent {
    private static List<Song> songs = new ArrayList<Song>();
    private static double totalSongCost = 0.0;
    private static int totalSongRating = 0;

    public static void main(String[] args) {
        populateSongs();

        for (Song song : songs) {
            totalSongCost  = songObj.getPrice();
            totalSongRating  = songObj.getRating();
        }
    }

    private void populateSongs() {
        songs.add(new Song(5, "Hey Jude", 12.5));
        songs.add(new Song(4, "Angie", 11.5));
        songs.add(new Song(0, "Other", 10.5));
    }
}
  

Ваш класс song будет просто таким:

 public class Song {
    private int rating = 0;
    private String title = "";
    private double price = 0.0;

    public Song(int rating, String title, double price) {
        this.rating = rating;
        this.title = title;
        this.price = price;
    }

    // Compressed for brevity
    public int getRating() { return rating; }
    public String getTitle() { return title; }
    public double getPrice() { return price; }
}