按前 3 个字符进行流分组

Stream grouping by first 3 chars

我有一个 phone 号码列表,我曾将其按国内(德国号码)/国际(世界其他地区)分组。示例列表如下所示:

List<String> list = new ArrayList<>();
list.add("+4969123");
list.add("+4989123");
list.add("+4930123");
list.add("+4365013");
list.add("+4369923");
list.add("+4365023");
list.add("+4176123");
list.add("+4178123");
list.add("+4179123");
list.add("+447782");
list.add("+447903");
list.add("+447701");

以及按前缀“+49”分组的方法

public static Map<Boolean,List<String>> national_International_Map(List<String> list){
    return list.stream().collect(Collectors.groupingBy(s -> s.startsWith("+49")));
}

然后我可以用 true 或 false 调用方法来将号码分离为国内/国际

List<String> nationalNums      = national_International_Map(list).get(true);
List<String> internationalNums = national_International_Map(list).get(false);

但现在要求已经改变,我必须按国家/地区对号码进行分组。目前只有四个国家。但以后可能会添加更多。为此,我考虑了以下几点,但如果我必须将更多国家分组,那就很复杂了。

public static Map<Boolean,List<String>> countryMap(List<String> list, String country){
    switch(country){
        case "de": return list.stream().collect(Collectors.groupingBy(s -> s.startsWith("+49")));
        case "at": return list.stream().collect(Collectors.groupingBy(s -> s.startsWith("+43")));
        case "ch": return list.stream().collect(Collectors.groupingBy(s -> s.startsWith("+41")));
        case "uk": return list.stream().collect(Collectors.groupingBy(s -> s.startsWith("+44")));
        default:   return null;
    }
}

并这样称呼它:

List<String> ukNums = countryMap(list,"uk").get(true);
List<String> chNums = countryMap(list,"ch").get(true);

有人可以告诉我我应该如何做到最好 - 也许不用一直扩展开关块?我想要类似的东西:

List<String> ukNums = countryMap(list).get("uk");

如果您定义 getCountryFromPhone 方法,则可以使用您目前使用的 groupingBy 方法按国家/地区对 phone 个号码进行分组:

Map<String, List<String>> groupedPhones = list.stream().collect(Collectors.groupingBy(s -> getCountryFromPhone(s)));

然后您可以按照自己的方式获得英国 phone 号码:groupedPhones.get("uk")

现在,getCountryFromPhone 是什么样子的?它应该 return phone 号码的国家/地区代码,因此以下内容适用于初学者。

static Map<String,String> phoneMap = Map.of(
    "+49", "de",
    "+43", "at",
    "+41", "ch",
    "+44", "uk");

private static String getCountryFromPhone(String s) {
    return phoneMap.getOrDefault(s.substring(0, 3), "unknown");
}

稍后,您可能需要添加对 phone 不同长度国家/地区代码的国家/地区的支持。这不是一件小事,有像 libphonenumber 这样的库可以帮助解决这个问题。您只需让 getCountryFromPhone 调用库中的适当方法即可。