0

I'm currently making a novel reader/editor in java using JSON. I've made the reader part with no problem, but the JSON serialization in the editor is giving me problems. The idea is to add or set an object to an ArrayList like this:

ArrayList<Chapters> allChapters = new ArrayList<>();

private void TAContentKeyTyped(java.awt.event.KeyEvent evt) {                                   
    Chapters newChapter = new Chapters(LSChapters.getSelectedValue(), TAContent.getText());
    if (allChapters.contains(newChapter)) {
        allChapters.set(0, newChapter);
    }
    else {
        allChapters.add(newChapter);
    }
    String json = gson.toJson(allChapters);
    Iterator allChaptersIterator = allChapters.iterator();
    while (allChaptersIterator.hasNext()) {
        System.out.println(allChaptersIterator.next().toString());
    }
    System.out.println(json);
}            

which outputs this when I press backspace 3 times:

Chapter: Test Content: 
Chapter: Test Content: 
Chapter: Test Content: 
[{"chapter":"Test","content":""},{"chapter":"Test","content":""},{"chapter":"Test","content":""}]

As you can see, instead of putting all inputs with the same chapter name into a single element, the code uses the .add() method instead of the .set() method every time despite putting a .contains() method on the if. Admittedly I didn't expect this approach to work, but I have no idea how to approach this at all.

The desired output should look like this:

Chapter: Test Content: This is content 1
Chapter: Test 2 Content: This is content 2
[{"chapter":"Test","content":"This is content 1"},{"chapter":"Test 2","content":"This is content 2"}]

Where every chapter with the same name is stored in a single element no matter how many keys were pressed.

Thank you in advance.

The Chapters class look like this:

public class Chapters {
    private String chapter;
    private String content;

    public Chapters(String chapter_name, String chapter_content) {
        chapter = chapter_name;
        content = chapter_content;
    }

    @Override
    public String toString() {
        return "Chapter: " + chapter + " Content: " + content;
    }
}

Notes: Please ignore that the .set() method uses index 0, that's just for testing. The real function would use the chapter name's index.

TMagnetB
  • 35
  • 8

2 Answers2

1

Maybe you should use Set instead of a List? Change your

ArrayList<Chapters> allChapters = new ArrayList<>();

to - for example :

Set<Chapters> chapters = new HashSet<>();

To Set function correctly you should also implement equals(..) and hashCode() in your Chapters, for example, if you can rely only chapter

@Override
public int hashCode() {
    return chapter.hashCode();
}

@Override
public boolean equals(Object obj) {
    if (obj != null) {
        if (obj instanceof Chapters) {
            return chapter.contentEquals(((Chapters) obj).getChapter());
        }
    }
    return false;
}

NOTE: above though working are just examples that use only chapter string as 'id' and not fully tested. See more What issues should be considered when overriding equals and hashCode in Java?.

There is no more need to check duplicates explicitly. You can just add chapters to your set and above changes will ensure no duplicates.

pirho
  • 11,565
  • 12
  • 43
  • 70
  • Thank you for your suggestion, but I got it working with list. Turns out putting your .add() or .set() methods in a keyboard event listener is a very bad idea. I copy-pasted the code to a button event, altered it a bit and it's good now. The new code will be on my answer. – TMagnetB Jul 03 '21 at 15:55
0

Turns out the main problem is the keyboard event. No matter which listener I use (KeyPressed, KeyReleased, KeyTyped) some kind of indexing error always pops up. I finally relented and gave the function its own button. It works perfectly now. This is the new code:

    try {
      String contentString = TAContent.getText();
      int contentStringLen = contentString.length();
      int selectedIndex = LSChapters.getSelectedIndex();
      int ArrayIndexLength = sessionContent.size();
      
      if (contentStringLen > 1) {
        if (ArrayIndexLength < selectedIndex) {
          for (int i = 0; i < selectedIndex; i++) {
            sessionContent.add(0, "");
          }
        }
                
        if (selectedIndex >= ArrayIndexLength) {
          sessionContent.add(selectedIndex, contentString);
        }
        else {
          sessionContent.set(selectedIndex, contentString);
        }
      }
      else {
        JOptionPane.showMessageDialog(null, "Please write chapter content first!");
      }
    }
    catch (Exception e) {
      System.err.println(e);
    }
TMagnetB
  • 35
  • 8