首页 > 解决方案 > 如何从多个列表中创建匹配对象列表并删除匹配列表中的对象,使其反映在原始列表中

问题描述

很抱歉,如果有人问过这个问题,但我在谷歌搜索中找不到类似的东西,所以就到这里。假设我有两个对象

笔记本

public class NoteBook {
    private String name;
    private String description;

    public NoteBook(String name, String description) {
        this.name = name;
        this.description = description;
    }
}

和笔记

public class Note {
    private String sourceNoteBook
    private String name;
    private String category;
    private String details;

    public Note(String sourceNoteBook,String name, String category, String details) {
        this.sourceNoteBook = sourceNoteBook;
        this.name = name;
        this.category = category;
        this.details = details;
    }
}

在程序中,用户可以创建多个 NoteBook 对象,每个 NoteBook 存储可变数量的 Notes。最终我想添加一个搜索功能,可以按类别或名称搜索笔记并返回找到的笔记列表。

通常我会使用 2 个 For 循环来遍历笔记本列表,然后遍历每个笔记本的笔记列表并比较字符串。像这样的东西:

    For (NoteBook noteBook: noteBooks) {
        For(Note note :noteBooks.getNoteList){
            if (note.getCategory().contains(someString)) {
                matchingNotes.add(notes);
            }
        }
    }

但是,我现在希望能够从 matchingNotes 列表中删除笔记,这样原始笔记本中的笔记也会被删除。

什么是存储和搜索这两个类的最佳方法,以便我可以实现这样的功能。

编辑:

只是为了澄清,最终结果是我希望用户能够在所有笔记本中搜索笔记类别,然后程序将返回与该类别匹配的笔记列表。然后他/她可以从该列表中删除一条笔记,这样它也可以在原始笔记本中删除。例如完全从程序中删除。

标签: java

解决方案


迭代器:
可能是最简单的解决方案。而且由于 java 在foreach循环中使用迭代器,因此性能是相同的。

For (NoteBook noteBook: noteBooks) {
  Iterator<Note> it = noteBooks.getNoteList().iterator();
  while (it.hasNext()) {
    Note note = it.next();
    if (note.getCategory().equals(someString)) {
      it.remove();
    }
  }
}

SQL:
这将是最佳的。然而,即使使用轻量级的东西,例如 H2 或 SQLite,也需要重构。而且在非常轻量级的应用程序中也不是一个选项。

高效:
如果您只按类别或名称搜索,您可以使用 2 个地图:

Map<String, Note> notesByCategory;
Map<String, Note> notesBytName

这将需要O(n)内存来存储地图,但会O(1)及时进行非常有效的查找(与当前的O(n)相比)。我会避免这种解决方案,因为很容易在笔记内容和地图之间实现不一致的状态。

编辑:

var newNoteNames = newList.stream().map(Note::getName).collect(Collectors.toSet());
var oldNoteNames = noteBooks.stream().flatMap(Notebook::getNodeList).map(Note::getName).collect(Collectors.toSet());

var removedNames = oldNoteNames.removeAll(newNoteNames);

for (var removedName : removedNames) {
  for (NoteBook noteBook: noteBooks) {
    Iterator<Note> it = noteBooks.getNoteList().iterator();
    while (it.hasNext()) {
      Note note = it.next();
      if (note.getName().contains(removedName)) {
        it.remove();
      }
    }
  }
}

推荐阅读