拆分字符串并将其存储到 HashMap java 8

Posted

技术标签:

【中文标题】拆分字符串并将其存储到 HashMap java 8【英文标题】:split string and store it into HashMap java 8 【发布时间】:2017-05-19 21:35:38 【问题描述】:

我想拆分下面的字符串并将其存储到 HashMap 中。

String responseString = "name~peter-add~mumbai-md~v-refNo~"; 

首先我使用分隔符连字符 (-) 拆分字符串并将其存储到 ArrayList 中,如下所示:

 public static List<String> getTokenizeString(String delimitedString, char separator) 
    final Splitter splitter = Splitter.on(separator).trimResults();
    final Iterable<String> tokens = splitter.split(delimitedString);
    final List<String> tokenList = new ArrayList<String>();
    for(String token: tokens)
        tokenList.add(token);
    
    return tokenList;

List<String> list = MyClass.getTokenizeString(responseString, "-");

然后使用下面的代码通过流将其转换为HashMap。

HashMap<String, String> = list.stream()
                          .collect(Collectors.toMap(k ->k.split("~")[0], v -> v.split("~")[1]));

流收集器不起作用,因为 refNo 没有任何值。

如果我在 ArrayList 中有偶数个元素,它可以正常工作。

有什么办法可以解决这个问题吗?还建议我如何使用 stream java 8 来完成这两个任务(我不想使用 getTokenizeString() 方法)。

【问题讨论】:

【参考方案1】:

首先,您不必将相同的String 拆分两次。 其次,检查数组的长度以确定给定键是否存在值。

HashMap<String, String> map= 
    list.stream()
        .map(s -> s.split("~"))
        .collect(Collectors.toMap(a -> a[0], a -> a.length > 1 ? a[1] : ""));

这是假设如果一个键没有对应的值,你想把一个带有null 值的键放入。

或者您可以跳过list 变量:

HashMap<String, String> map1 = 
    MyClass.getTokenizeString(responseString, "-")
        .stream()
        .map(s -> s.split("~"))
        .collect(Collectors.toMap(a -> a[0], a -> a.length > 1 ? a[1] : ""));

【讨论】:

感谢您的快速回复。似乎它只会在〜而不是连字符上分裂。还有我怎样才能摆脱第一个 getTokenizeString() 方法。 我试过你的代码。它抛出 NullPointerException。它只适用于偶数大小的列表。 @SangamBelose 此代码假定您保留List&lt;String&gt; list = MyClass.getTokenizeString(responseString, "-"); 即使我保留 MyClass.getTokenizeString(responseString, "-");它抛出空指针。它在最后一个数组值上失败。【参考方案2】:

除非Splitter 有什么魔法,否则getTokenizeString 方法在这里已经过时了。您可以将整个处理作为单个操作执行:

Map<String,String> map = Pattern.compile("\\s*-\\s*")
    .splitAsStream(responseString.trim())
    .map(s -> s.split("~", 2))
    .collect(Collectors.toMap(a -> a[0], a -> a.length>1? a[1]: ""));

通过使用正则表达式 \s*-\s* 作为分隔符,您将空格视为分隔符的一部分,因此隐式修剪条目。在处理条目之前只有一个初始 trim 操作,以确保在第一个条目之前或最后一个条目之后没有空格。

然后,只需在map 步骤中拆分条目,然后再收集到Map

【讨论】:

非常感谢您快速有效的回答。像魅力一样工作。 正在使用split() 两次,一次用于-,另一次用于~ ok?? @VishwaRatna 因为这是两个独立的操作,具有不同的语义,独立执行它们没有任何问题。您应该避免的是执行冗余操作,例如 split("~") 在原始代码中对同一输入执行两次。【参考方案3】:
private final String dataSheet = "103343262,6478342944, 103426540,84528784843, 103278808,263716791426, 103426733,27736529279, 
103426000,27718159078, 103218982,19855201547, 103427376,27717278645, 
103243034,81667273413";

    final int chunk = 2;
    AtomicInteger counter = new AtomicInteger();
    Map<String, String> pairs = Arrays.stream(dataSheet.split(","))
            .map(String::trim)
            .collect(Collectors.groupingBy(i -> counter.getAndIncrement() / chunk))
            .values()
            .stream()
            .collect(toMap(k -> k.get(0), v -> v.get(1)));

结果:

pairs =
 "103218982" -> "19855201547"
 "103278808" -> "263716791426"
 "103243034" -> "81667273413"
 "103426733" -> "27736529279"
 "103426540" -> "84528784843"
 "103427376" -> "27717278645"
 "103426000" -> "27718159078"
 "103343262" -> "6478342944"

我们需要将每 2 个元素分组为键值对,因此将列表分成 2 个块,(counter.getAndIncrement() / 2) 将产生相同的数字,每 2 个命中例如:

IntStream.range(0,6).forEach((i)->System.out.println(counter.getAndIncrement()/2));
prints:
0
0
1
1
2
2

您可以使用相同的想法将列表划分为块。

【讨论】:

【参考方案4】:

另一个简短的方法:

String responseString = "name~peter-add~mumbai-md~v-refNo~";
Map<String, String> collect = Arrays.stream(responseString.split("-"))
                              .map(s -> s.split("~", 2))
                              .collect(Collectors.toMap(a -> a[0], a -> a.length > 1 ? a[1] : ""));
                              System.out.println(collect);

首先您根据 - 拆分字符串,然后像 map(s -&gt; s.split("~", 2))it 那样映射以创建 Stream&lt;String[]&gt;[name, peter][add, mumbai][md, v][refNo, ] 一样,最后您将其收集到 toMap,因为 a[0] 转到键和a[1] 值。

【讨论】:

以上是关于拆分字符串并将其存储到 HashMap java 8的主要内容,如果未能解决你的问题,请参考以下文章

在python中拆分键值字符串并将其移动到df列中

如何拆分/解析 JSON 数据并将其保存到 SQL 服务器中?

在Java中拆分一个字符串并将其插入一个空字符串

拆分用逗号分隔的字符串并将值存储到 int 数组中

在Java中将字符串拆分为字符串和int [重复]

拆分具有多个分隔符的字符串并将其保存到向量中