在Collection中搜索键/值对,如果成功匹配,则返回该Collection中的所有值

时间:2015-07-30 21:31:01

标签: java collections

我的最后一次尝试得到了很好的解释,所以很有希望得到更清晰的解释。

我有一个具有以下数据结构的Collection。

    LinkedHashMap<String, String> currentHashMap = new LinkedHashMap<String, String>();
    currentHashMap.put("id","12345");
    currentHashMap.put("firstName","John");
    currentHashMap.put("lastName","Doe");

    haystack.add(currentHashMap);

*重复约250,000个条目

我需要搜索每个列表条目中的HashMaps,检查密钥是否存在,以及它是否具有相应的值。如果是,我想返回该特定hashmap中的所有值

这是我目前正在使用的代码。

private TreeSet<String> searchWithinCollection(List<LinkedHashMap<String, String>> haystack, String needle, String needleKey) {

    TreeSet<String> returnValueSet = new TreeSet<>();

    for (LinkedHashMap<String, String> mappedData : haystack) {
                  System.out.println(mappedData.values());
        for (Entry<String, String> specificData : mappedData.entrySet()) {
            if (needleKey.equals(specificData.getKey()) && needle.equals(specificData.getValue())) {
                //where I want to collect the values within the current hashmap, as it's satisfied the search criteria
                                   //the current code would only return the current key/balue pair, even if all values were collected outside the for loop. Instead, I'd want to collect "12345", "John", "Doe" if needleKey = id and needle = 12345.
            }
        }
    }

    return returnValueSet;
}

我想要的是,如果当前集合中的某个键等于&#34; id&#34;,并且它的值等于&#34; 12345&#34;,那么我可以返回所有该特定集合中的值(并使用上面的示例,将是&#34; 12345&#34;,&#34; John&#34;,&#34; Doe&#34;)。 我能做的最好的就是返回第一个键/值,这显然不是很有用。尝试捕获第二个for循环外的mappedData中的所有值都没有带来任何结果(无论是创建Collection的新实例,克隆还是有什么东西。)。我还发现没有什么可以手动推进每个循环中的指针来手动捕获Collection中的所有值。

编辑:如果有帮助,那么有一个System.out.println(mappedData.values());我可以得到我期望的值,但如果在if语句中访问values(),则只返回示例中的id。

3 个答案:

答案 0 :(得分:4)

您不应该遍历hashmap中的所有条目(当前,代码中的循环for (Entry<String, String> specificData : mappedData.entrySet())。这会破坏维护hashmap的目的。

相反,内循环应该变为

String potentialNeedle = mappedData.get(needleKey);
if (needle.equals(potentialNeedle))
    returnValueSet.addAll(mappedData.values());

答案 1 :(得分:2)

您正在使用地图,就好像它是一个条目列表,这完全违背了地图的目的:快速访问给定密钥的值:

for (Map<String, String> mappedData : haystack) {
    String value = mappedData.get(needleKey);
    if (needle.equals(value)) {
        returnValueSet.addAll(mappedData.values());
    }
}

答案 2 :(得分:1)

也许您应该重新设计帐户以提高效果。为您要搜索的每个字段创建一个地图可能很聪明。而不是你的干草堆创建你的数据结构:

public class PersonDataManager {
    private final Map<Integer, Map<String, String>> baseData;
    private final Map<String, List<Integer>> firstNameLookupMap;
    private final Map<String, List<Integer>> lastNameLookupMap;


    public PersonDataManager(){
        this.baseData = new HashMap<>();
        this.firstNameLookupMap = new HashMap<>();
        this.lastNameLookupMap = new HashMap<>();
    }


    public void addPerson(Integer id, String firstName, String lastName){
        //try to find existing person to update:
        Map<String, String> personMap = baseData.get(id);
        if(personMap == null){
            personMap = new HashMap<>();
            baseData.put(id, personMap);
        }
        personMap.put("firstName", firstName);
        personMap.put("lastName", lastName);

        //add to lookup-maps
        addLookupName(firstNameLookupMap, id, firstName);
        addLookupName(lastNameLookupMap, id, lastName);
    }


    private static void addLookupName(Map<String, List<Integer>> nameMap, Integer id, String name){
        //get existing list of the name:
        List<Integer> idList = nameMap.get(name);
        if(idList == null){
            idList = new ArrayList<>();
        }

        if(!idList.contains(id)){
            idList.add(id);
        }
    }


    private List<Map<String, String>> searchByName(Map<String, List<Integer>> nameMap, String name){
        List<Integer> matchingIds = nameMap.get(name);
        List<Map<String, String>> result = new ArrayList<>();
        if(matchingIds != null){
            for(Integer id : matchingIds){
                result.add(searchById(id));
            }
        }

        return result;
    }


    public Map<String, String> searchById(Integer id){
        return baseData.get(id);
    }


    public List<Map<String, String>> searchByFirstName(String name){
        return searchByName(firstNameLookupMap, name);
    }


    public List<Map<String, String>> searchByLastName(String name){
        return searchByName(lastNameLookupMap, name);
    }
}

通过这种方式,您可以轻松获取使用其ID的人的哈希映射。如果您需要使用名字或姓氏进行搜索,则可以使用其他地图来获取匹配的人员ID。希望这有帮助

编辑:刚刚实现了一个完全符合我认为你可能需要的课程。玩得开心;)