将文件中的键值对添加到 Hashmap

Adding key value pairs from a file to a Hashmap

我正在尝试将键值对从文件中提取到 Hashmap 中以便于对值进行操作。

文件格式如下:

Activity1:3:Activity2:5:Activity3:7:
Activity4:1: 

每行最多有3个活动及其对应的编号。

String currentPath;
Path fullPath;
HashMap<String, String> hm = new HashMap<>();

try {
    // Obtain current directory path
    currentPath = Paths.get("").toAbsolutePath().toString();
    // Obtain full path of data.txt
    fullPath = Paths.get(currentPath, "data.txt");
    // Check if file exists
    if (Files.exists(fullPath)) {
        // Read line by line in data.txt
        Files.lines(fullPath)
                .forEach(line -> hm.put(line.split(":")[0], line.split(":")[1]) );
    }
    else{
        System.out.println("data.txt is not found.");
    }
} catch (
        IOException e) {
    e.printStackTrace();
}

但是,只有第一个 key:value 对被插入到 Hashmap 中。 我尝试使用

.map(s -> s.split(":"))
.collect(Collectors.toMap(r -> r[0], r -> r[1] ))

但它不起作用,因为 split() 输出类型是 toMap 不接受的数组。

编辑:

public static void main(String[] args) {

        String currentPath;
        Path filePath;
        HashMap<String, String> hm = new HashMap<>();
        Pattern delimiter = Pattern.compile(":");

        try {
            // Obtain current directory path
            currentPath = Paths.get("").toAbsolutePath().toString();
            // Obtain full path of data.txt
            filePath = Paths.get(currentPath, "data.txt");
            // Check if file exists
            if (Files.exists(filePath)) {
                // Read line by line in data.txt
                    hm = Files.lines(filePath)
                        .map(delimiter::split) // stream of multiple Array<String>
                        .flatMapToInt(a -> IntStream.range(0, a.length - 1))  // combine multiple Array<String> to a
                            // single stream, remove last Array<String>
                        .filter(i -> i % 2 == 0)  // obtain only even indices
                        .mapToObj(i -> new AbstractMap.SimpleEntry<>(a[i], a[i+1])) // a cannot be resolved. Create new Map, key is Array<String>[even], value is Array<String>[odd]
                        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a,b) -> a)); //
            }
            else{
                System.out.println("data.txt not found.");
            }
        } catch (
                IOException e) {
            e.printStackTrace();
        }

        for (String objectName : hm.keySet()) {
            System.out.println(objectName);
            System.out.println(hm.get(objectName));
        }
    }

Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself. Questions without a clear problem statement are not useful to other readers. See: How to create a Minimal, Reproducible Example.

这个问题很好地说明了为什么需要 MRE 以及为什么它如此有用。
当把数据硬编码成 mre 时,你很快意识到问题与文件无关:

    String line = "Activity1:3:Activity2:5:Activity3:7:" ;
    String[] lineAsArray = line.split(":"); 

    //lineAsArray is of the following stucture [Activity1, 3, Activity2, 5, Activity3, 7]
    //by line.split(":")[0], line.split(":")[1]) you simply add Activity1, 3
    //to get all pairs iterate over the array:
    for(int index = 0; index < lineAsArray.length ; index+=2){
        System.out.println("key = "+ lineAsArray[index]+ " value = "+ lineAsArray[index+1]);
    }

分析

当前的实现不包括一行包含许多键值对的情况。

解决方案

考虑到一行可能包含许多键值对,以下草案解决方案执行行解析。

import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public final class Main {
    public static void main(final String[] args) {
        final List<String> lines = new ArrayList<>();
        lines.add("Activity1:3:Activity2:5:Activity3:7:");
        lines.add("Activity4:1:");

        final Map<String, String> map = lines
            .stream()
            .map(Main::parseLine)
            .flatMap(List::stream)
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        System.out.println(map);
    }

    private static List<Map.Entry<String, String>> parseLine(final String line) {
        final List<Map.Entry<String, String>> entries = new ArrayList<>();
        final String[] components = line.split(":");
        final int pairCount = components.length / 2;
        for (int pairNumber = 0; pairNumber < pairCount; ++pairNumber) {
            final int pairStartIndex = pairNumber * 2;
            entries.add(
                new AbstractMap.SimpleEntry<>(
                    components[pairStartIndex],
                    components[pairStartIndex + 1]
                )
            );
        }
        return entries;
    }
}

输出:

{Activity3=7, Activity4=1, Activity1=3, Activity2=5}

首先让我们看一下为什么您的解决方案没有给出预期的结果。当您围绕分隔符 : 拆分每一行时,可能会有许多键值对。但是您只考虑第一个键值对而忽略其余部分。所以这适用于您示例中的最后一行,因为它只有一个对应的地图条目。同时它不适用于第一行,因为它有许多对应的映射条目,而您只处理第一个条目。

这是我解决这个问题的方法。获取文件中的每一行并将其拆分为分隔符 :。这会为每个对应的行生成一个数组。由于每一行都有一个尾随 : 字符,因此您必须跳过数组中相关的最后一个元素。然后数组中的每个偶数索引成为映射中的键,紧随其后的奇数索引成为相应的值。这是它的样子。

private static final Pattern DELIMITER = Pattern.compile(":");
Map<String, String> activityMap = lines.map(DELIMITER::split)
    .flatMap(a -> IntStream.range(0, a.length - 1).filter(i -> i % 2 == 0)
        .mapToObj(i -> new AbstractMap.SimpleEntry<>(a[i], a[i + 1])))
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> a));

输出如下所示:

{Activity3=7, Activity4=1, Activity1=3, Activity2=5}

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;

public class Demo {

public static void main(String args[])throws IOException {

    /Example :- File file = new File("src/abc.txt");/
    File file = new File("<absolute_file_path>");
    if(file.exists()) {
        BufferedReader br = new BufferedReader(new FileReader(file));
        String data = null;
        HashMap<String, String> hashMap = new HashMap<>();
        while ((data = br.readLine()) != null) {
            String[] str = data.split(":");
            for (int i = 1; i < str.length; i += 2) {
                hashMap.put(str[i - 1], str[i]);
            }
        }
        System.out.println(hashMap);
        br.close();
    }else
        System.out.println("File not exists");

  }
}

输出如下所示:

{Activity3=7, Activity4=1, Activity1=3, Activity2=5}