简体   繁体   中英

What JavaFX data structure should I use in the following example?

I have the following class GroupStudentsBySurname and it contains the following data structure HashMap<String, ArrayList<Student>> . Each Student object contains two attributes: surname and english_score

The keys are the surname of students taken from the Student object Student.surname . For a particular key Lee , it has an ArrayList<Student> where the Students share the same surname .

One of the method of this GroupStudentsBySurname class is to compute the average_english_score for Students having the same surname.

I would use a TableView data structure for the class GroupStudentsBySurname , which looks like the following:

 Surname |  average_english_score    <- column headings
    Lee  |      65
   Chan  |      86
   Smith |      76

I want to be able to use track the changes of class GroupStudentsBySurname every time I add/delete a Student object from the arraylist, which in turn affects the average_english_score attribute.

Question: I do not know what data structure from javafx I should use in this case? Would I need to use ObservableMap or ObservableList to track the changes whenever I add / delete a Student object.

JavaFX is a UI technology, so not entirely sure what you mean be 'data structure from JavaFX'.

Anyway, let's start with the data model (we'll get to the UI later).

First I think you need to introduce another class (which requires a valid implementation of equals and hashCode on Student ):

public class StudentGroup
{
  private Set<Student> students = new HashSet<>();
  private BigDecimal englishTotal = BigDecimal.ZERO;

  public BigDecimal getEnglishAverage()
  {
    return englishTotal.divide(students.size());
  }

  public Collection<Student> getStudents()
  {
    return Collections.unmodifiableCollection(students);
  }

  public void addStudent(Student student)
  {
    if (students.add(student))
    {
      englishTotal.add(student.getEnglishScore());
    }
  }

  public void removeStudent(Student student)
  {
    if (students.remove(student))
    {
      englishTotal.subtract(student.getEnglishScore());
    }
  }
}

Your class GroupStudentsBySurname then becomes:

public class GroupStudentsBySurname
{
  private Map<String, StudentGroup> students = new HashMap<>();

  ...
}

Then create an adapter row class, which will allow StudentGroup to be used in more grouping scenarios than just being grouped by surname and is what will be used with JavaFX:

public class StudentBySurnameRow
{
  private SimpleStringProperty surname;
  private SimpleStringProperty groupSize;
  private SimpleStringProperty englishAverage;

  public StudentBySurnameRow(String surname, StudentGroup studentGroup)
  {
    this.surname = new SimpleStringProperty(surname);
    this.groupSize = new SimpleStringProperty(Integer.toString(studentGroup.getStudents().size()));
    this.englishAverage = new SimpleStringProperty(studentGroup.getEnglishAverage().toString());
  }

  ...
}

Once you have these classes they can be slotted into a JavaFX TableView as per the Oracle TableView tutorial where you would create an ObservableList like this:

List<StudentBySurnameRow> studentBySurnameRows = new ArrayList<>();
for (Map.Entry<String, StudentGroup> entry : groupStudentsBySurname.getStudents().entrySet())
{
  studentBySurnameRows.add(new StudentBySurnameRow(entry.getKey(), entry.getValue()));
}

table.setItems(FXCollections.observableArrayList(studentBySurnameRows));

I would use either a ListView or a TableView . In your case, if you just want to be able to manipulate the list, the first would be more practical. Otherwise, if you really want to use the whole map, the latter.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM