繁体   English   中英

当字符串在 Java 8 中没有分隔符时,根据提供的键从字符串创建 Map

[英]Creating a Map from a string based on the provided Keys when the string doesn't have delimiters in Java 8

给定以下String

String s = "DIMENSION 24cm 34cm 12cm DETAILED SPECIFICATION Twin/Twin XL Flat Sheet: 105"l x 74"w. CARE For best results, machine wash warm with like colors. COLOURS red blue green"; 

关键是 = DIMENSIONS, DETAILED SPECIFICATION, CARE, COLOURS

我们需要创建Map<String,String> ,其中将如上所示,相应的文本将是

地图的内容将如下所示:

DIMENSION: 24cm 34cm 12cm,
DETAILED SPECIFICATION: Twin/Twin XL Flat Sheet: 105"l x 74"w,
CARE:  For best results, machine wash warm with like colors,
COLOURS: red blue green 

并且没有必要所有这些都存在于字符串中。

假设输入String中不存在CARE

String s = "DIMENSION 24cm 34cm 12cm DETAILED SPECIFICATION Twin/Twin XL Flat Sheet: 105"l x 74"w. COLOURS red blue green"; 

地图的内容将如下所示:

DIMENSION: 24cm 34cm 12cm,
DETAILED SPECIFICATION: Twin/Twin XL Flat Sheet: 105"l x 74"w,
COLOURS: red blue green 

即,如果给定字符串中不存在,则相应的也将不存在。 例如, DIMENSION不存在,字符串以"DETAILED SPECIFICATION ... "开头。

由于字符串没有分隔符,我无法从中创建地图。

使用平面 Java,我可以这样做:

if(s.contains("ASSEMBLY")) {
    ass = s.substring(s.indexOf("COLOURS") + 8);
    s = s.replaceAll(s.substring(s.indexOf("COLOURS")),"");
}
if(s.contains("OVERALL")){
    ov = s.substring(s.indexOf("CARE") + 5);
    s = s.replaceAll(s.substring(s.indexOf("CARE")),"");
}
if(s.contains("CARE")){
    care1 = s.substring(s.indexOf("DETAILED SPECIFICATION") + 24);
    s = s.replaceAll(s.substring(s.indexOf("DETAILED SPECIFICATION")),"");
}
if(s.contains("DIMENSIONS")){
    de1 = s.substring(s.indexOf("DIMENSIONS") + 11);
    s =s.replaceAll(s.substring(s.indexOf("DIMENSIONS")),"");
}

如果我们有分隔符,那么我可以这样做。

Map<String, String> map = Stream.of(s)
    .map(s -> s.split("="))
    .collect(Collectors.toMap(s -> s[0], s -> s[1]));

正则表达式方法:

    String s = "DIMENSION 24cm 34cm 12cm DETAILED SPECIFICATION Twin/Twin XL Flat Sheet: 105 w. COLOURS red blue green";
    String[] keys = new String[]{"DIMENSION", "DETAILED SPECIFICATION", "CARE", "COLOURS"};
    String keyRegex = String.join("|", keys);
    Pattern p = Pattern.compile("(?<key>" + keyRegex + ") (?<value>((?!(" + keyRegex + ")).)*)");
    Matcher m = p.matcher(s);

    Map<String, String> result = new HashMap<>();
    while (m.find()) {
        result.put(m.group("key"), m.group("value"));
    }

您可以从给定的生成正则表达式并将其编译为模式

我使用lookaheadlookbehind解决了这个问题:

public static Pattern getPattern(Collection<String> keys) {
    String joinedKeys = String.join("|", keys);
    String regex = String.format("(?<=%s)|(?=%s)", joinedKeys, joinedKeys); // creates a regex "(?<=DIMENSION|DETAILED\\sSPECIFICATION|CARE|COLOURS)|(?=DIMENSION|DETAILED\\sSPECIFICATION|CARE|COLOURS)"
    return Pattern.compile(regex);
}
  • (?=foo) - Lookahead - 匹配紧跟在foo之后的位置;
  • (?<=foo) - Lookbehind - 匹配紧接在foo之前的位置。

有关更多信息,请查看本教程

当我们有一个模式时,我们可以使用Pattern.splitAsStream()生成一个流。

public static Map<String, String> toMap(String source, Set<String> keys) {
    
    return getPattern(keys).splitAsStream(source)
        .collect(combineByKey(keys));
}

这个流的每个元素要么是要么是,为了获得流执行结果的映射,我们需要一个能够区分收集器

我们可以使用Collector.of()创建这样的收集器。 作为一个可变容器,我将使用map-entriesDeque

可以在下面的累加器函数中观察到的将空字符串用作的情况表示当线程获取从而不是开始的数据时并行执行流时可能发生的情况,换句话说,一个和一个在不同的容器中 当我们在组合器函数中合并容器时,这个问题得到了解决。

StringBuilder用作的中间类型,由Map.entry()返回的条目是不可变的。

注意: Map.entry()是在 Java 9 中引入的。要使此解决方案与Java 8兼容,请改用new AbstractMap.SimpleEntry<>()请参阅 JDK 8 的代码)。

public static Collector<String, ?, Map<String, String>> combineByKey(Set<String> keys) {

    return Collector.of(
        ArrayDeque::new,
        (Deque<Map.Entry<String, StringBuilder>> deque, String next) -> {
            if (keys.contains(next)) deque.add(Map.entry(next, new StringBuilder()));
            else {
                if (deque.isEmpty()) deque.add(Map.entry("", new StringBuilder(next)));
                else deque.getLast().getValue().append(next);
            }
        },
        (left, right) -> {
            if (!right.isEmpty() && !left.isEmpty() && right.getFirst().getKey().isEmpty()) {
                left.getLast().getValue().append(right.pollFirst().getValue());
            }
            left.addAll(right);
            return left;
        },
        deque -> deque.stream().collect(Collectors.toMap(
            Map.Entry::getKey,
            entry -> entry.getValue().toString().strip()
        ))
    );
}

main()

public static void main(String[] args) {
    String source = "DIMENSION 24cm 34cm 12cm DETAILED SPECIFICATION Twin/Twin XL Flat Sheet: 105l x 74w. CARE For best results, machine wash warm with like colors. COLOURS red blue green";

    Set<String> keys = Set.of("DIMENSION", "DETAILED SPECIFICATION", "CARE", "COLOURS");

    Map<String, String> result = toMap(source, keys); // converting the source string to map
    
    result.forEach((k, v) -> System.out.println(k + " -> " + v)); // printing the result
}

输出:

COLOURS -> red blue green
DIMENSION -> 24cm 34cm 12cm
DETAILED SPECIFICATION -> Twin/Twin XL Flat Sheet: 105l x 74w.
CARE -> For best results, machine wash warm with like colors.

在线演示的链接

这可能会帮助您:

String str = "DIMENSION 24cm 34cm 12cm DETAILED SPECIFICATION Twin/Twin XL Flat Sheet: 105 w. CARE For best results, machine wash warm with like colors. COLOURS red blue green";

    String[] keys = {"DIMENSIONS", "DETAILED SPECIFICATION", "CARE", "COLOURS"};

    Map<String, String> map = new LinkedHashMap<>();

    for (int index = 0; index < keys.length; index++) {

        String subString = "";
        if(index + 1 < keys.length) {
            int start = str.indexOf(keys[index] + " ") > 0 ? str.indexOf(keys[index] + " ") + keys[index].length() : str.indexOf(keys[index]);
            int end = str.indexOf(keys[index + 1]);
            if(start < 0 || end < 0) {
                continue;
            }
            subString = str.substring(start, end);
        }  else {
            subString = str.substring(str.indexOf(keys[index] + " "));
        }
        map.put(keys[index], subString);
    }
    System.out.println(map);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM