通过Java8函数获得结果的最佳方法是什么?

时间:2019-05-31 14:11:38

标签: java java-8 java-stream

我需要过滤元素,然后根据某些列进行排序。发布,我将需要根据列的组合查找唯一的条目。由于是文件处理,因此使用pipe(|)作为分隔符来表示列值。

String s1= "12|Thor|Asgaurd|1000000|Avenger|Active"
String s2= "234|Iron man|New York|9999999|Avenger|Active"
String s3= "420|Loki|Asgaurd|||Inactive"
String s4= "12|Thor|Asgaurd Bank|1000000|Avenger HQ|Active"

首先需要根据活动/不活动状态过滤数据。然后,需要根据第4列对其进行排序。最后,需要通过合并列1,2,3来保持唯一性。

预期输出=

"234|Iron man|New York|9999999|Avenger|Active"
"12|Thor|Asgaurd|1000000|Avenger|Active"

4 个答案:

答案 0 :(得分:1)

创建模型类并解析字符串是解决问题的方法,但是如果您不想这样做,可以这样做:

import java.util.Comparator;
import java.util.stream.Collectors;
import java.util.stream.Stream;

List<String> result = Stream.of(s1, s2, s3, s4)
            .filter(s -> s.split("\\|")[5].equals("Active"))
            .sorted(Comparator.comparing(e -> e.split("\\|")[4]))
            .collect(Collectors.toList());

答案 1 :(得分:0)

当所有内容仅是字符串时,似乎无法过滤。 试试这个,

  

创建一个可以容纳您的列的新模型类。   例如:

class MyData{
 private String name;
 private String city;
 private String distance;
 private String organization;
 private String status;
 //And create Getter Setter method for all above fields.
}
  

现在进入您的主班,您可以在其中玩代码。

Map<MyData> map = new HashMap<MyData>();
 MyData myData = new MyData();
 myData.setName("Thor");
 myData.setCity("Asgaurd");
 myData.setDistance("1000000");
 myData.setOrganization("Avenger");
 myData.setStatus("Active");
 map.put(12, myData);
//Same thing for all other data (note: use the loop for data insertion in map)

Map<String, MyData> sorted = map.entrySet().stream().sorted(comparingByValue()).collect(toMap(e -> e.getKey(), e -> e.getValue().getName(), (e1, e2) -> e2,LinkedHashMap::new));

System.out.println("map after sorting by values: " + sorted);

答案 2 :(得分:0)

您可以通过以下方式解决您的任务:

首先,只需创建POJO(普通的旧Java对象)并覆盖toString()方法。

class MarvelPerson {

    private Integer id;
    private String name;
    private String origin;
    private Integer point = null;
    private String faction;
    private String status;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getOrigin() {
        return origin;
    }

    public void setOrigin(String origin) {
        this.origin = origin;
    }

    public Integer getPoint() {
        return point;
    }

    public void setPoint(Integer point) {
        this.point = point;
    }

    public String getFaction() {
        return faction;
    }

    public void setFaction(String faction) {
        this.faction = faction;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append(id);
        builder.append("|");
        builder.append(name);
        builder.append("|");
        builder.append(origin);
        builder.append("|");
        if(point != null) {
            builder.append(point);
        }
        builder.append("|");
        if(faction != null) {
            builder.append(faction);
        }
        builder.append("|");
        builder.append(status);

        return builder.toString();
    }
}

然后,您应该将解析器从字符串写入MarvelPerson旁注:小心,我的实现非常基础,我认为应该对其进行修改,因为我可能没有预见到某些极端情况。

class PersonParser {

    static MarvelPerson parse(String data) {
        MarvelPerson person = new MarvelPerson();

        String[] array = data.split("\\|", -1);

        person.setId(Integer.parseInt(array[0]));
        person.setName(array[1]);
        person.setOrigin(array[2]);

        if(!array[3].isEmpty()) {
            person.setPoint(Integer.parseInt(array[3]));
        }

        if(!array[4].isEmpty()) {
            person.setFaction(array[4]);
        }

        person.setStatus(array[5]);

        return person;
    }

}

然后是您的解决方案:

public class Test {

    public static void main(String[] args) {
        List<MarvelPerson> list = new ArrayList<>();

        list.add(PersonParser.parse("12|Thor|Asgaurd|1000000|Avenger|Active"));
        list.add(PersonParser.parse("234|Iron man|New York|9999999|Avenger|Active"));
        list.add(PersonParser.parse("420|Loki|Asgaurd|||Inactive"));
        list.add(PersonParser.parse("12|Thor|Asgaurd Bank|1000000|Avenger HQ|Actie"));

        list.stream()
                .filter(marvelPerson -> marvelPerson.getStatus().equals("Active"))
                .sorted((o1, o2) -> o1.getPoint() <= o2.getPoint() ? 1 : -1)
                .forEach(marvelPerson -> {
                    System.out.println(marvelPerson.toString());
                });
    }

}

要打印的输出:

  

234 |钢铁侠|纽约| 9999999 |复仇者|活跃   12 | Thor | Asgaurd | 1000000 | Avenger | Active

答案 3 :(得分:0)

首先,您应该创建一个代表您的String数据的对象。像这样:

public IActionResult Result

使用此方法,您可以从字符串创建对象流,然后再进行过滤,排序和不同的操作:

public class MyObject {
    private int id;
    private String name;
    private String location;
    private Integer value;
    private String category;
    private String state;

    public MyObject(String entry) {
        String[] parts = entry.split("\\|");
        if (parts.length != 6) {
            throw new IllegalArgumentException("entry has not 6 parts");
        }
        id = Integer.parseInt(parts[0]);
        name = parts[1];
        location = parts[2];
        try {
            value = Integer.parseInt(parts[3]);
        } catch (NumberFormatException ignored) {
        }
        category = parts[4];
        state = parts[5];
    }

    // getters

    @Override
    public String toString() {
        return String.join("|", String.valueOf(id), name, location, String.valueOf(value), category, state);
    }
}

在映射操作之后,您可以按状态过滤值,并按第4列(在我的情况下为Collection<MyObject> result = Stream.of(s1, s2, s3, s4) .map(MyObject::new) .filter(o -> "Active".equals(o.getState())) .sorted(Comparator.comparing(MyObject::getValue).reversed()) .collect(Collectors.toMap(o -> Arrays.asList(o.getId(), o.getName()), Function.identity(), (o1, o2) -> o1, LinkedHashMap::new)) .values(); result.forEach(System.out::println); )对其进行排序。最后,您将映射中的所有值收集到不同的操作中。将您需要区分的所有值添加到value。映射将所有原始值(Arrays.asList()用作值。对于重复项,我们保留第一个值(Function.identity()),并使用(o1, o2) -> o1保留项目的顺序。最后,只使用地图的值。

如果您需要LinkedHashMap而不是List,请使用Collection

结果将是这样:

new ArrayList(result)