应该在Java中使用哪种数据结构

时间:2017-11-10 07:06:33

标签: java data-structures computer-science

假设有三个变量," 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>>();

但问题是,树图取代了之前的值,因为该值必须是唯一的。例如,当我把

&lt; 9600001,info2001,Tue3&gt;和&lt; 9600001,info2001,Thu9&gt;进入地图,

在散列图中

应该有

9600001,info2001 - Tue3和Thu9

但替换了之前的值,因此只存在一个值:

9600001,info2001 - Thu9

有人可以告诉我如何处理这个问题吗?

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

4 个答案:

答案 0 :(得分:3)

使用List条记录。

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

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

Map的{​​{1}}

List

答案 1 :(得分:0)

您需要为此问题创建自定义对象和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会为您提供staffId的数量,subject的大小将为您提供明确的统计数字subject

答案 2 :(得分:0)

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));

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

答案 3 :(得分:0)

虽然计数公式有点奇怪(计算不同主题+计数sessionTime),但我猜你的意思是Map<Integer, Map<String, List<String>>>。我已经提出了两种方法,如有必要请修改。

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;
//    }

}