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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41483398/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 23:24:33  来源:igfitidea点击:

split string and store it into HashMap java 8

javaarraylisthashmapjava-8java-stream

提问by Sangam Belose

I want to split below string and store it into HashMap.

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

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

first I split the string using delimeter hyphen (-) and storing it into ArrayList as below:

首先,我使用分隔符连字符 (-) 拆分字符串并将其存储到 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, "-");

and then using the below code to convert it to HashMap using stream.

然后使用以下代码使用流将其转换为 HashMap。

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

The stream collector doesnt work as there is no value against refNo.

流收集器不起作用,因为没有针对 refNo 的值。

It works correctly if I have even number of elements in ArrayList.

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

Is there any way to handle this? Also suggest how I can use stream to do these two tasks (I dont want to use getTokenizeString() method) using stream java 8.

有没有办法处理这个?还建议我如何使用流 java 8 使用流来完成这两个任务(我不想使用 getTokenizeString() 方法)。

采纳答案by Holger

Unless Splitteris doing any magic, the getTokenizeStringmethod is obsolete here. You can perform the entire processing as a single operation:

除非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]: ""));

By using the regular expression \s*-\s*as separator, you are considering white-space as part of the separator, hence implicitly trimming the entries. There's only one initial trimoperation before processing the entries, to ensure that there is no white-space before the first or after the last entry.

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

Then, simply split the entries in a mapstep before collecting into a Map.

然后,map在收集到一个Map.

回答by Eran

First of all, you don't have to split the same Stringtwice.
Second of all, check the length of the array to determine if a value is present for a given key.

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

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

This is assuming you want to put the key with a nullvalue if a key has no corresponding value.

这是假设null如果键没有对应的值,您想为键放置一个值。

Or you can skip the listvariable :

或者您可以跳过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] : ""));

回答by Mohamed.Abdo

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)));

result:

结果:

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

We need to group each 2 elements into key, value pairs, so will partion the list into chunks of 2, (counter.getAndIncrement() / 2) will result same number each 2 hits ex:

我们需要将每 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

You may use the same idea to partition list into chunks.

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

回答by Vishwa Ratna

Another short way to do :

另一种简短的方法:

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);

First you split the String on basis of -, then you map like map(s -> s.split("~", 2))it to create Stream<String[]>like [name, peter][add, mumbai][md, v][refNo, ]and at last you collect it to toMapas a[0]goes to key and a[1]goes to value.

首先,您根据 拆分字符串-,然后将map(s -> s.split("~", 2))它映射为创建Stream<String[]>like [name, peter][add, mumbai][md, v][refNo, ],最后将其收集到toMapasa[0]转到键和a[1]转到值。