【问题标题】:Nested Classes, Nested Lists, or Maps?嵌套类、嵌套列表或映射?
【发布时间】:2017-05-25 06:42:06
【问题描述】:

在通读嵌套类、嵌套列表和映射之后,我仍然无法确定使用的正确方法,甚至无法确定如何实现这三种方法。

目标:从一个日志文件中跟踪多个服务正常运行时间的统计信息。每个服务状态更改都在一行中,包含 Name、oldStatus、newStatus 和 timeChanged

最后,我想看看这些行之间的时间,但现在我只是想正确地组织数据。

目前,我正在使用一个类,这里​​是它的构建:

public class Services {
    private List<String> AllServices = new ArrayList<String>();
    // Initial thought of adding another list here, containing
    // the variables, but how would I associate that to the
    // service above?
    private List<String> ServiceStatus;



    public boolean AddService(String name) {
        if (!AllServices.contains(name)) {
            AllServices.add(name);
            return true;
        }
        return false;
    }

    public List<String> GetServices() {
        return AllServices;
    }
}

这一切都很好。当解析器发现一个新服务时,它会将其添加到列表中,因此不会有重复。然后,每次发现服务状态发生变化时,我都会继续添加。我不知道如何为每项服务存储这些数据。

我想我可以把它比作使用唯一标识符为服务名称的数据库,保存每次状态更改、更改内容和时间的记录。一旦我把它记下来,我就可以开始比较两者之间的时间了。

最初想在这里添加另一个列表,包含变量,但我如何将它与每个服务关联?

我考虑过数组,但在 Java 中它们看起来相当静态,因为必须调整它们的大小以添加更多数据。我已经忘记了在 PHP 中解决这个问题的方法,但根据我过去有限的经验,我记得能够构建和使用数组,例如:

statusChanged = myServices["TheService"][i][date];
statusChangedTo = myServices["TheService"][i][new_status];
statusChangedTo = myServices["OtherService"][i][date];
statusChangedTo = myServices["OtherService"][i][new_status];

AllServices
 |- TheService
 |   |- TimeDate
 |       | - New Status
 |       | - Old Status
 |- OtherService
     |- TimeDate
         | - New Status
         | - Old Status

这使我走上了使用扩展类的道路。我可以有服务和服务。服务将导致只有一个服务列表,但是服务如何再次将其基础变量与父服务类中列出的特定服务相关联?

再一次,在阅读了太多与我想要完成的任务相似但与我不一样的示例后,我觉得我想多了。或者,我只是完全脱离了墙,可能有更好的方法。

【问题讨论】:

  • myServices.get("TheService").newStatus 将是一种更“Java 方式”。无论如何,Java 不是 PHP。
  • “它将它添加到列表中,因此没有重复。”在这种情况下使用HashSet会更好。
  • 旁注:阅读有关命名约定的信息。例如,变量名采用驼峰式命名,而不是 AllServices!
  • @user2864740 确实,它不是 PHP。我正在尝试学习 Java 方式并完全同意。我想你最终也用这个暗示回答了我的问题。
  • @GhostCat 我会更深入地研究 HashSet,谢谢。哈!也谢谢你的旁注。 :) 非常感谢。

标签: java arrays list class arraylist


【解决方案1】:

我建议使用任何数据库来保存记录的事件。在服务多、事件多的情况下,这是首选的解决方案。

否则,我提供了几个步骤将它们存储在内存中:

首先,您应该按服务名称划分数据。使用Map&lt;K,V&gt;

其次,我建议你将oldStatusnewStatustimeChanged组合成ServiceEvent类:

public class ServiceEvent {
    private final String oldStatus;
    private final String newStatus;
    private final DateTime timeChanged;
    // methods...
}

在事件序列无序的情况下,通过timeChangedComparator 对事件进行排序是很方便的:

public class ServiceEventComparator implements Comparator<ServiceEvent> {
    @Override
    public int compare(ServiceEvent e1, ServiceEvent e2) {
        return e1.getTimeChanged().compareTo(e2.getTimeChanged());
    }
}

因此,您的ServiceEventRepository 可以是这样的:

public class ServiceEventRepository {
    private Map<String, SortedSet<ServiceEvent>> storage = new HashMap<>();

    public void addEvent(String service, ServiceEvent event) {
        SortedSet<ServiceEvent> events = storage.get(service);
        if (events == null) {
            events = new TreeSet<ServiceEvent>(new ServiceEventComparator());
            storage.put(service, events);
        }
        events.add(event);
    }
}

如果事件序列具有自然顺序,请使用简单的List&lt;ServiceEvent&gt;

请注意,上面的ServiceEventRepository 不是线程安全的

【讨论】:

  • 这太棒了。非常感谢。我还在玩它——我应该提到我是一个业余爱好者,所以我还有一些工作要做。
  • 不客气!请随时提出有关它的具体问题。
  • 最终,我需要一个数据库(我接受你所有的“我告诉过你的”)。但我不想浪费@Gregory.K 的时间,所以我实现了这个。这正是我最初想要的。不过,当我走这条路时,我只处理了 3 个文件。现在它有超过 100 个文件和超过 20,000 行。我没有看到这一点,所以,我将转向 SQLite 或更高版本。感谢您的教育和时间!对于需要存储对象属性的人来说,这仍然非常有用。人
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-02
  • 2018-04-21
  • 2016-02-12
  • 2020-02-04
  • 2021-08-09
  • 2020-03-06
  • 1970-01-01
相关资源
最近更新 更多