Java:通过匹配 LinkedHashMap 中的相似键来复制值

Java: copy values by matching similar keys from LinkedHashMap

我有一个 LinkedHashMap 并想执行以下操作:

  1. 遍历 HashMap 并检查 Key 中的字符串是否包含 'Group' 个单词
  2. 创建与该键字符串匹配的所有值的字符串[]

例如,如果我有如下所示的 LinkedHashMap

HashMap<String, String> nameNum = new LinkedHashMap<String, String>();
nameNum.put("row 1", "data 1");
nameNum.put("Group_Colour_R", "Red");
nameNum.put("Group_Colour_B", "Blue");
nameNum.put("row 4", "data 4");
nameNum.put("row 5", "data 5");
nameNum.put("Group_Shape_R", "Rectangle");
nameNum.put("Group_Shape_T", "Triangle");
nameNum.put("Group_Shape_C", "Circle");
nameNum.put("row 9", "data 9");
nameNum.put("row 10", "data 10");
nameNum.put("row 11", "data 11");

循环上面的HashMap后,应该有2个String[]

String[] colour = {"Red", "Blue"}; 
String[] shape = {"Rectangle", "Triangle", "Circle"};

我只是不确定如何实现它。

有和我想要的相关的东西,在这里找到了:Partial search in HashMap

基于上面的内容,我按如下方式实现了它,但是,如您所见,它多次运行相同的值。我不确定何时以及如何打破循环,以便它只给出一次值:

import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import org.apache.commons.lang3.StringUtils;

public class MainClass {
    public static void main(String[] args) {
        SortedMap<String, String> nameNum = new TreeMap<String, String>();
        nameNum.put("row 1", "data 1");
        nameNum.put("Group_Colour_R", "Red");
        nameNum.put("Group_Colour_B", "Blue");
        nameNum.put("row 4", "data 4");
        nameNum.put("row 5", "data 5");
        nameNum.put("Group_Shape_R", "Rectangle");
        nameNum.put("Group_Shape_T", "Triangle");
        nameNum.put("Group_Shape_C", "Circle");
        nameNum.put("row 9", "data 9");
        nameNum.put("row 10", "data 10");
        nameNum.put("row 11", "data 11");


        for (Map.Entry<String, String> entry : nameNum.entrySet()) {
            String prefix = entry.getKey();
            if (prefix.contains("Group")) {
                prefix = prefix.substring(0, StringUtils.lastIndexOf(prefix, "_"));
                System.out.println("******");
                for (Map.Entry<String, String> entry1 : filterPrefix(nameNum, prefix).entrySet()) {
                    System.out.println(entry1);
                }
                System.out.println("******");
            }
        }
    }

    public static <V> SortedMap<String, V> filterPrefix(SortedMap<String,V> baseMap, String prefix) {
        if(prefix.length() > 0) {
            char nextLetter = (char) (prefix.charAt(prefix.length() -1) + 1);
            String end = prefix.substring(0, prefix.length()-1) + nextLetter;
            return baseMap.subMap(prefix, end);
        }
        return baseMap;
    }
}

理想情况下,我想使用 LinkedHashMap,因为我想保留顺序。我非常感谢任何 pointers/code 如何实现类似的东西。任何代码片段将不胜感激。提前致谢。

请删除 for 循环以避免出现多个重复结果。您需要使用 "Group_"Colour" 和 "Group_Shade" 作为过滤器方法的前缀进行两次调用,以获得所需的结果。

也许 Java 8 Stream API 在这里会有帮助。您可以尝试使用 Collectors.groupingBy:

将相关条目分组在一起
Map<String,List<String>> groups =
    nameNum.entrySet()
           .stream()
           .filter(entry -> entry.getKey().contains("Group"))
           .collect(Collectors.groupingBy(entry -> entry.getKey().substring(0, entry.getKey().lastIndexOf("_")),
                                          Collectors.mapping(Map.Entry::getValue,
                                                             Collectors.toList()));

这会产生一个 Map 包含:

{Group_Shape=[Rectangle, Triangle, Circle], Group_Colour=[Red, Blue]}

如果您愿意,也可以强制输出 MapLinkedHashMap

Map<String,List<String>> groups =
    nameNum.entrySet()
           .stream()
           .filter(entry -> entry.getKey().contains("Group"))
           .collect(Collectors.groupingBy(entry -> entry.getKey().substring(0, entry.getKey().lastIndexOf("_")),                     
                                          LinkedHashMap::new, 
                                          Collectors.mapping(Map.Entry::getValue,
                                                             Collectors.toList()));

这会改变输出的迭代顺序 Map:

{Group_Colour=[Red, Blue], Group_Shape=[Rectangle, Triangle, Circle]}

您可以使用 HashMap 代替数组来存储 Group 值,如下所示:

HashMap<String,ArrayList<String>> groupList = new HashMap<String, ArrayList<String>>();

然后在循环内部,您可以实现以下逻辑来存储相应的组键及其值:

if(prefix.contains("Group")){
    String keyGrp = prefix.split("_")[1];
    if(groupList.containsKey(keyGrp)){
        groupList.get(keyGrp).add(entry.getValue());
    }else{
        ArrayList<String> grpVal = new ArrayList<String>();
        grpVal.add(entry.getValue());
        groupList.put(keyGrp, grpVal);
    }
}