Java 8流:如何在两个字符串的ArrayList之间匹配值并创建另一个对象的列表

问题描述

我有两个字符串列表,想要比较列表中的值并构造另一个对象的新列表。我能够使用嵌套循环来做到这一点,但正在寻找一种更高性能,更整洁的解决方案。

List<String> list1 = new ArrayList();
list1.add("A,Airplane");
list1.add("B,Boat");

List<String> list2 = new ArrayList();
list2.add("A90,Boing Airplane");
list2.add("A70,Boing777");
list2.add("B80,Boing Boat");

一个Vehicle对象。

class Vehicle {

private String model;
private String submodel;
private String type;
private String subtype;
// setters getters
}

现在,我需要通过将模型(list1中的第一个字符)与list2中的第一个字符进行匹配来构建车辆对象,并构建类似这样的东西

private List<Vehicle> buildVehicle(List<String> list1,List<String> list2) {
        List<Vehicle> vehicles = new ArrayList<>();
        if (ObjectUtils.isNotEmpty(list2)) {
            list2.forEach(v -> {
                Vehicle vehicle = new Vehicle();
                if (v.contains(",")) {
                    String[] val = StringUtils.split(v,",");
                    vehicle.setSubtype(val[0]);
                    vehicle.setSubmodel(val[1]);
                }
                for (String c : list1) {
                    //Matching the first character from element in list1 
                    if (c.substring(0,1).equals(vehicle.getSubtype().substring(0,1))
                            && c.contains(",")) {
                        String[] val = StringUtils.split(c,");
                        vehicle.setType(val[0]);
                        vehicle.setModel(val[1]);
                        }
                        break;
                    }
                }
                vehicles.add(vehicle);
            });
        }
        return vehicles;
    }

是否可以通过使用流来避免嵌套循环?

解决方法

我将遵循以下方法:

List<String> list1 = new ArrayList<>();
list1.add("A,Airplane");
list1.add("B,Boat");

List<String> list2 = new ArrayList<>();
list2.add("A90,Boing Airplane");
list2.add("A70,Boing777");
list2.add("B80,Boing Boat");

Pattern commaPattern = Pattern
    .compile("\\s*,\\s*"); // a regex pattern to split by comma and the whitespace around it

Map<String,String> modelToType = list1.stream().map(commaPattern::split)
    .collect(Collectors
        .toMap(modelAndType -> modelAndType[0],modelAndType -> modelAndType[1])); // mapping models to types for o(1) lookups

List<Vehicle> vehicles = list2.stream().map(commaPattern::split)
    .map(subModelAndSubType -> {
      Vehicle vehicle = new Vehicle();
      vehicle.submodel = subModelAndSubType[0];
      vehicle.subtype = subModelAndSubType[1];
      vehicle.model = vehicle.submodel.substring(0,1);
      vehicle.type = modelToType.get(vehicle.model);
      return vehicle;
    }).collect(Collectors.toList());
,

提供的数据。

List<String> list1 = new ArrayList<>();
list1.add("A,Boeing Airplane");
list2.add("A70,Boeing777");
list2.add("B80,Boeing Boat");

无论如何获取模型类型信息,如果您不是使用Lists来保存信息,而是使用Maps来进行转换,此转换可能会更加高效,当然也更容易。如果从文件中读取了信息,则最好在读取文件时对其进行预处理(如果需要,则进行拆分)并将其放入地图中。如果是手工输入的,那么将信息放在地图中将根本不需要任何预处理。这是一个简单的例子。

Map<String,String> map1 = new HashMap<>();
map1.put("A","Airplane");
map1.put("B","Boat");

但是,请按照此处提供的信息进行操作。

首先,我创建了一个Lambda来协助列表转换。

Function<List<String>,Map<String,String>> makeMap =
        lst -> lst.stream().map(st -> st.split("\\s*,\\s*")).collect(
                Collectors.toMap(a -> a[0],a -> a[1]));

// create the TypeModel map
Map<String,String> mapTM = makeMap.apply(list1);
// create the subTypeSubModel Map;
Map<String,String> mapSTSM = makeMap.apply(list2);

现在只需使用每个键集将它们组合在一起即可。 我在示例中为imho制作的Vehicle创建了一个构造函数 更干净的对象创建。

List<Vehicle> vehicles = mapTM.keySet().stream()
        .flatMap(type -> mapSTSM.keySet().stream()
                .filter(subType -> subType.startsWith(type))
                .map(sbType -> new Vehicle(mapTM.get(type),mapSTSM.get(sbType),type,sbType)))
        .collect(Collectors.toList());

vehicles.forEach(System.out::println);

基于toString进行打印(可以更改)。

[Airplane,Boeing Airplane,A,A90]
[Airplane,Boeing777,A70]
[Boat,Boeing Boat,B,B80]

这是班级的无用者和吸气剂。

class Vehicle {
    
    private String model;
    private String submodel;
    private String type;
    private String subtype;
    
    public Vehicle() {
    }
    
    public Vehicle(String model,String submodel,String type,String subtype) {
        this.model = model;
        this.submodel = submodel;
        this.type = type;
        this.subtype = subtype;
    }
    
    public String toString() {
       return "[" + String.join(",",model,submodel,subtype)
                + "]";
    }
}