简体   繁体   English

将单链表转换为地图

[英]Converting singly linked list to a map

I have been given an assignment to change to upgrade an existing one. 我被赋予了改变以升级现有的任务。

Figure out how to recode the qualifying exam problem using a Map for each terminal line, on the assumption that the size of the problem is dominated by the number of input lines, not the 500 terminal lines 在假设问题的大小由输入线的数量而不是500个终端线控制的情况下,弄清楚如何使用每个终端线的Map重新编码合格的考试问题

The program takes in a text file that has number, name. 该程序接收一个具有数字,名称的文本文件。 The number is the PC number and the name is the user who logged on. 该号码是PC号码,名称是登录的用户。 The program returns the user for each pc that logged on the most. 该程序返回登录最多的每台PC的用户。 Here is the existing code 这是现有的代码

public class LineUsageData {
    SinglyLinkedList<Usage> singly = new SinglyLinkedList<Usage>();


    //function to add a user to the linked list or to increment count by 1
    public void addObservation(Usage usage){
        for(int i = 0; i < singly.size(); ++i){
            if(usage.getName().equals(singly.get(i).getName())){
                singly.get(i).incrementCount(1);
                return;
            }
        }

        singly.add(usage);
    }
    //returns the user with the most connections to the PC
    public String getMaxUsage(){
        int tempHigh = 0;
        int high = 0;
        String userAndCount = "";
        for(int i = 0; i < singly.size(); ++i){//goes through list and keeps highest
            tempHigh = singly.get(i).getCount();
            if(tempHigh > high){
                high = tempHigh;
                userAndCount = singly.get(i).getName() + " " + singly.get(i).getCount();
            }
        }

        return userAndCount;
    }
}

I am having trouble on the theoretical side. 我在理论方面遇到麻烦。 We can use a hashmap or a treemap. 我们可以使用hashmap或treemap。 I am trying to think through how I would form a map that would hold the list of users for each pc? 我正在考虑如何构建一个能够保存每台PC用户列表的地图? I can reuse the Usage object which will hold the name and the count of the user. 我可以重用Usage对象,该对象将保存用户的名称和计数。 I am not supposed to alter that object though 我不应该改变那个对象

When checking if Usage is present in the list you perform a linear search each time ( O(N) ). 检查列表中是否存在Usage ,每次都执行线性搜索( O(N) )。 If you replace your list with the Map<String,Usage> , you'll be able to search for name in sublinear time. 如果使用Map<String,Usage>替换列表,则可以在次线性时间内搜索name TreeMap has O(log N) time for search and update, HashMap has amortized O(1) (constant) time. TreeMap具有O(log N)时间用于搜索和更新, HashMap具有分摊O(1) (常数)时间。

So, the most effective data structure in this case is HashMap . 因此,在这种情况下最有效的数据结构是HashMap

import java.util.*;

public class LineUsageData {
    Map<String, Usage> map = new HashMap<String, Usage>();

    //function to add a user to the map or to increment count by 1
    public void addObservation(Usage usage) {
        Usage existentUsage = map.get(usage.getName());
        if (existentUsage == null) {
            map.put(usage.getName(), usage);
        } else {
            existentUsage.incrementCount(1);
        }
    }

    //returns the user with the most connections to the PC
    public String getMaxUsage() {
        Usage maxUsage = null;
        for (Usage usage : map.values()) {
            if (maxUsage == null || usage.getCount() > maxUsage.getCount()) {
                maxUsage = usage;
            }
        }

        return maxUsage == null ? null : maxUsage.getName() + " " + maxUsage.getCount();
    }

    // alternative version that uses Collections.max
    public String getMaxUsageAlt() {
        Usage maxUsage = map.isEmpty() ? null :
                Collections.max(map.values(), new Comparator<Usage>() {
                    @Override
                    public int compare(Usage o1, Usage o2) {
                        return o1.getCount() - o2.getCount();
                    }
                });

        return maxUsage == null ? null : maxUsage.getName() + " " + maxUsage.getCount();
    }

}

Map can also be iterated in the time proportional to it's size, so you can use the same procedure to find maximum element in it. Map也可以在与其大小成比例的时间内迭代,因此您可以使用相同的过程来查找其中的最大元素。 I gave you two options, either manual approach, or usage of Collections.max utility method. 我给了你两个选项,手动方法或Collections.max实用方法的使用。

With simple words: You use a LinkedList (singly or doubly) when you have a list of items, and you usually plan to traverse them, and a Map implementation when you have "Dictionary-like" entries, where a key corresponds to a value and you plan to access the value using the key. 用简单的单词:当你有一个项目列表时,你使用LinkedList (单独或双重),你通常计划遍历它们,当你有“类字典”条目时,你可以使用一个Map实现,其中一个键对应一个值并且您计划使用密钥访问该值。

In order to convert your SinglyLinkedList to a HashMap or TreeMap , you need find out which property of your item will be used as your key (it must be an element with unique values). 要将SinglyLinkedList转换为HashMapTreeMap ,您需要找出项目的哪个属性将用作您的键(它必须是具有唯一值的元素)。

Assuming you are using the name property from your Usage class, you can do this (a simple example): 假设您正在使用Usage类中的name属性,您可以这样做(一个简单的示例):

//You could also use TreeMap, depending on your needs.
Map<String, Usage> usageMap = new HashMap<String, Usage>();

//Iterate through your SinglyLinkedList.
for(Usage usage : singly) {
    //Add all items to the Map
    usageMap.put(usage.getName(), usage);
}

//Access a value using its name as the key of the Map.
Usage accessedUsage = usageMap.get("AUsageName");

Also note that: 另请注意:

Map<string, Usage> usageMap = new HashMap<>();

Is valid, due to diamond inference . 由于钻石推断 ,有效。

I Solved this offline and didn't get a chance to see some of the answers which looked to be both very helpful. 我离线解决了这个问题,没有机会看到一些看起来非常有帮助的答案。 Sorry about that Nick and Aivean and thanks for the responses. 对Nick和Aivean抱歉,并感谢您的回复。 Here is the code i ended up writing to get this to work. 这是我最终编写的代码,以使其工作。

public class LineUsageData {

    Map<Integer, Usage> map = new HashMap<Integer, Usage>();
    int hash = 0;
    public void addObservation(Usage usage){
        hash = usage.getName().hashCode();
        System.out.println(hash);
        while((map.get(hash)) != null){
            if(map.get(hash).getName().equals(usage.name)){
                map.get(hash).count++;
                return;
            }else{
                hash++;
            }

        }
        map.put(hash, usage);
    }






    public String getMaxUsage(){
        String str = "";
        int tempHigh = 0;
        int high = 0;

    //for loop
        for(Integer key : map.keySet()){
            tempHigh = map.get(key).getCount();
            if(tempHigh > high){
                high = tempHigh;
                str = map.get(key).getName() + " " + map.get(key).getCount();
            }
        }

        return str;
    }


}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM