【问题标题】:Which data structure should be used in JavaJava应该使用哪种数据结构
【发布时间】:2017-11-10 07:06:32
【问题描述】:

假设有“staffId”、“subject”和“sessionTime”三个变量

示例如下:

<9600001, info2001, Tue3>,
<9600001, info2002, Wed4>,
<9600002, info2001, Wed2>,
<9600001, info2001, Thu9>,
<9600001, info2003, Fri10>,
<9600002, info2004, Wed4>

最后输出应该是:

STAFF_ID HOURS
 9600002 4
 9600001 7

计算:观察到员工 9600001 有 4 个实际会话,涉及 3 个不同的科目,所以这 总共需要 4+3=7 小时。

为了编写这个问题,我决定使用嵌套的 HashMap,比如

Map<Integer, Map<String, String>> submission = new HashMap<Integer, TreeMap<String, String>>();

但问题是,树状图替换了它以前的值,因为该值必须是唯一的。例如,当我把

和 进入地图,

在哈希图中,应该有

9600001, info2001 - Tue3 和 Thu9

但是之前的值被替换了,所以只有一个值存在:

9600001, info2001 - Thu9

谁能告诉我如何解决这个问题?

我应该使用哪些数据结构?

【问题讨论】:

  • Map&lt;StaffIdType, List&lt;SomeStruct&gt;&gt;,其中SomeStruct 包含主题和会话时间字段。
  • 为什么不同的主题会在总时间上增加一个小时?员工 1 有 4 个一小时的课程,员工 2 有 2 个。为什么不同的科目会增加总小时数?

标签: java data-structures computer-science


【解决方案1】:

使用List 的记录。

class Record {
  int staffId;
  String subject;
  String sessionTime;
}

List<Record> submissions = new ArrayList<>();

MapList

class Record {
  String subject;
  String sessionTime;
}

Map<Integer, List<Record>> submissions = new HashMap<>();

【讨论】:

  • 首选第一个选项。 Java 毕竟是一种基于类/对象的语言。保持简单:)
  • 我不确定它在性能方面是否更可取。要在第一个选项中获取 staffId X 的所有记录,您必须遍历整个列表。而在第二个选项中,您可以通过密钥获取它们。
  • new Map&lt;&gt;() 不正确。它应该是 Map 的实现,例如 new HashMap&lt;&gt;();
  • @Synch 对,我用 HashMap 替换了 Map,用 ArrayList 替换了 List。性能 - 如果您计算一次,那么列表版本会更快,因为地图构建也不是免费的。所以我对“哪个更好”问题的回答是“这取决于”:)
  • 是的,当然这取决于。我的意思是@JackFlamp 的评论说第一个选项更可取,就好像它是一成不变的。 List vs Map 的一般规则是,如果您的列表很小,则 List 获胜,否则 Map 获胜。
【解决方案2】:

您需要为此问题创建一个自定义对象和一个Map

Map<Integer, CustomObject> map = new HashMap<Integer, CustomObject>();

class CustomObject {
    int staffIdCount; //Number of distinct staffId records (e.g. for 9600001 value will be 4)
    Set<String> subject = new HashSet<String>(); //distinct subjects
}

功能如下:

遇到9600001时执行以下操作

    if(map.containsKey(9600001))
    {
        CustomObject tmp = map.get(9600001);
        tmp.staffIdCount+=1;
        tmp.subject.add("info2001"); //the corresponding subject
        map.put(9600001, tmp);
    }
    else
    {
        CustomObject tmp = new CustomObject();
        tmp.staffIdCount +=1;
        tmp.subject.add("info2001");

        map.put(9600001, tmp);
    }

编辑: 所以staffIdCount 会给你staffIds 的数量和subject 的大小会给你subject 的不同数量

【讨论】:

    【解决方案3】:

    Java 是一种面向对象的语言,因此您最好创建类来表示您想要记录和操作的项目。在您的情况下,有工作人员、主题和会议:

    class Staff {
        private final String id;
    }
    
    class Subject {
        private final String id;
    }
    
    class Session {
        private final Staff staff;
        private final Subject subject;
        int period;
    }
    

    如果你有一个会话列表,那么你可以很容易地生成一张从员工到时间总和的地图(例如):

    List<Session> sessions;
    
    Map<Staff, Integer> staffTotalTime = sessions.stream()
        .collect(groupingBy(Session::getStaff, summingInt(Session::getPeriod));
    

    我的建议是不要从建模数据开始优化访问。表单数据结构是对象之间关系的简单而优雅的表示,然后在需要时将其操作为其他形式。将上面的语句更改为按主题求和或创建平均值或其他任何内容都将是微不足道的,而无需更改用于存储对象的数据模型。

    【讨论】:

      【解决方案4】:

      虽然计数公式有点奇怪(计数不同的主题 + 计数 sessionTime),但我猜你的意思是 Map&lt;Integer, Map&lt;String, List&lt;String&gt;&gt;&gt;。我想出了两种方法,如有需要请修改。

      public class Dummy {
      
          public Map<Integer, Integer> countHours(List<Submission> submissions) {
      
              Map<Integer, Integer> res = new HashMap<>();
              Map<Integer, Set<String>> subjectMap = new HashMap<>();
              Map<Integer, List<String>> sessionTimeMap = new HashMap<>();
      
              for (Submission s : submissions) {
                  subjectMap.computeIfAbsent(s.getStaffId(), v -> new HashSet<>()).add(s.getSubject());
                  sessionTimeMap.computeIfAbsent(s.getStaffId(), v -> new ArrayList<>()).add(s.getSessionTime());
              }
      
              for (Map.Entry<Integer, Set<String>> e : subjectMap.entrySet()) {
                  res.put(e.getKey(), e.getValue().size());
              }
      
              for (Map.Entry<Integer, List<String>> e : sessionTimeMap.entrySet()) {
                  res.merge(e.getKey(), e.getValue().size(), Integer::sum);
              }
      
              return res;
          }
      
          public Map<Integer, Integer> countHours2(List<Submission> submissions) {
      
              Map<Integer, Map<String, Long>> collect = submissions.stream()
                      .collect(Collectors.groupingBy(Submission::getStaffId,
                              Collectors.groupingBy(Submission::getSubject, Collectors.counting())));
      
              return collect.entrySet().stream()
                      .collect(Collectors.toMap(Map.Entry::getKey,
                              e -> e.getValue().size() +
                                      e.getValue().values().stream().mapToInt(Number::intValue).sum()));
          }
      
          @Test
          public void test() {
      
              List<Submission> submissions = new ArrayList<>();
              submissions.add(new Submission(9600001, "info2001", "Tue3"));
              submissions.add(new Submission(9600001, "info2002", "Wed4"));
              submissions.add(new Submission(9600002, "info2001", "Wed2"));
              submissions.add(new Submission(9600001, "info2001", "Thu9"));
              submissions.add(new Submission(9600001, "info2003", "Fri10"));
              submissions.add(new Submission(9600002, "info2004", "Wed4"));
      
              System.out.println(countHours(submissions)); // {9600002=4, 9600001=7}
      
              System.out.println(countHours2(submissions)); // {9600002=4, 9600001=7}
          }
      
      }
      
      // In case you have lombok
      @Data
      @AllArgsConstructor
      class Submission {
      
          private int staffId;
          private String subject;
          private String sessionTime;
      
          // In case you do not have lombok
      
      //    Submission(int staffId, String subject, String sessionTime) {
      //        this.staffId = staffId;
      //        this.subject = subject;
      //        this.sessionTime = sessionTime;
      //    }
      //
      //    public int getStaffId() {
      //        return staffId;
      //    }
      //
      //    public void setStaffId(int staffId) {
      //        this.staffId = staffId;
      //    }
      //
      //    public String getSubject() {
      //        return subject;
      //    }
      //
      //    public void setSubject(String subject) {
      //        this.subject = subject;
      //    }
      //
      //    public String getSessionTime() {
      //        return sessionTime;
      //    }
      //
      //    public void setSessionTime(String sessionTime) {
      //        this.sessionTime = sessionTime;
      //    }
      
      }
      

      【讨论】:

        猜你喜欢
        • 2013-07-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-12
        • 1970-01-01
        • 1970-01-01
        • 2012-07-21
        • 1970-01-01
        相关资源
        最近更新 更多