将输入的文件转换为内部列表映射的映射

时间:2019-05-01 22:38:20

标签: string java-8 hashmap java-stream

我从文件读取中输入了以下内容,

1|VegemiteScroll|VS5|3|6.99
2|VegemiteScroll|VS5|5|8.99

3|BlueberryMuffin|MB11|2|9.95
4|BlueberryMuffin|MB11|5|16.95
5|BlueberryMuffin|MB11|8|24.95

6|Croissant|CF|3|5.95
7|Croissant|CF|5|9.95



我想使用group by将其放在Hashmap中,如下所示,让我们考虑#1,#2行。

Map obj = new HashMap();
obj.put(3,6.99);
obj.put(5,8.99);

List<Map> list = new ArrayList<>();
list.add(obj)

Map<String, List<Map>> map = new HashMap();
map.put("VS5", list);

这是针对第一种情况,对于第二和第三种情况(#3至#8),

map.put("MB11", list);  

该列表包含上面的地图列表。您能不能请我使用java8流解决这个问题。预先感谢!

2 个答案:

答案 0 :(得分:1)

下面是用于目的的代码。尚未完全优化。但这是有效的。

    import java.io.File;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Scanner;

    /**
     * 
     */

    /**
     * @author KishorRaskar
     *
     */
    public class Main {

        /**
         * @param args
         * @throws Exception 
         */
        public static void main(String[] args) throws Exception {
            // pass the path to the file as a parameter 
            File file = 
              new File("C:\\Data\\FAB\\WorkSpace\\Test\\MyCode\\test.txt"); 
            Scanner sc = new Scanner(file); 
            List<HashMap> mapList = new ArrayList<>();
            HashMap<String, String> dataMap = null;
            HashMap<String, List<HashMap<String, String>>> dataMapList = new HashMap<>();

            while (sc.hasNextLine()) {
                String line = sc.nextLine();
                if(null == line || line.isEmpty()) {
                    continue;
                }
                String[] dataArray = line.split("\\|");
                //System.out.println(Arrays.toString(dataArray)); 
                String dataMapKey = dataArray[3].trim();
                String dataMapValue = dataArray[4].trim();
                String dataMapListKey = dataArray[2].trim();            
                if(!dataMapList.containsKey(dataMapListKey)) {
                    dataMapList.put(dataMapListKey, new ArrayList<>());
                    dataMapList.get(dataMapListKey).add(new HashMap<>());
                }
                dataMapList.get(dataMapListKey).get(0).put(dataMapKey, dataMapValue);
              //System.out.println(line); 
            }
            System.out.println("###############################");
            System.out.println(dataMapList);
            System.out.println("###############################");
          } 
    }

输入:test.txt 1 |素食滚动| VS5 | 3 | 6.99 2 |素食滚动| VS5 | 5 | 8.99

3 |蓝莓松饼| MB11 | 2 | 9.95 4 |蓝莓松饼| MB11 | 5 | 16.95 5 |蓝莓松饼| MB11 | 8 | 24.95

6 |羊角面包| CF | 3 | 5.95 7 |羊角面包| CF | 5 | 9.95 8 |羊角面包| CF | 9 | 16.99

输出:

##############################

{CF = [{3 = 5.95,5 = 9.95,9 = 16.99}],MB11 = [{2 = 9.95,5 = 16.95,8 = 24.95}],VS5 = [{3 = 6.99,5 = 8.99}]} ##############################

答案 1 :(得分:1)

这是一个使用Java 8 Streams,groupingBy和其他“奇特的东西”的解决方案。为了简单起见,我假设输入已经作为字符串提供了。

private static final int EXPECTED_LINE_ELEMENTS = 5;      
private static final int LINE_KEY_INDEX = 2;              
private static final int DATA_KEY_INDEX = 3;              
private static final int DATA_VALUE_INDEX = 4;            

private static Map<String, List<Map<Integer, Float>>> convert(final String input) {                                                                                            
    return Stream.of(input.split("\\n")) // split input by new line character                                                                                                  
        .filter(line -> !line.trim().isEmpty()) // filter out empty lines                                                                                                            
        .map(line -> line.split("\\|")) // split each line by '|' character                                                                                                          
        .filter(line -> line.length == EXPECTED_LINE_ELEMENTS) // filter out potential elements containing undesired number of columns                                   
        .collect(Collectors.groupingBy(line -> line[LINE_KEY_INDEX])) // convert to map using 3rd column as a key and a list of corresponding lines as values            
        .entrySet()                                                                                                                                                            
        .stream()                                                                                                                                                              
        .collect(                                                                                                                                                              
            Collectors.toMap(                                                                                                                                                  
                Map.Entry::getKey, // keep the same key                                                                                                                       
                stringListEntry -> Collections.singletonList(convertLinesToMap(stringListEntry.getValue())) // convert list of lines to a singleton list containing a map      
            )                                                                                                                                                                  
        );                                                                                                                                                                     
}                                                                                                                                                                              

private static Map<Integer, Float> convertLinesToMap(final List<String[]> lines) {                                                                                             
    return lines.stream()                                                                                                                                                      
        .collect(Collectors.toMap(                                                                                                                                             
            line -> Integer.valueOf(line[DATA_KEY_INDEX].trim()), // use 4th column as key of the map (mapped to Integer)                                                
            line -> Float.valueOf(line[DATA_VALUE_INDEX].trim())) // use 5th column as key of the map (mapped to Float)                                                  
        );                                                                                                                                                                     
}                                                                                                                                                                                                                                                                 

然后,以下内容:

System.out.println(convert(input));

应打印以下内容:

{ CF =[{3=5.95, 5=9.95, 9=16.99}],  VS5 =[{3=6.99, 5=8.99}],  MB11 =[{2=9.95, 5=16.95, 8=24.95}]}

PS。如您所写:

Map obj = new HashMap();
obj.put(3,6.99);
obj.put(5,8.99);

我假设您想将Integers作为键,将Floats作为值。如果不是这种情况,则可以只更新convertLinesToMap方法的适当片段。