Ashish Goel
Ashish Goel

Reputation: 39

What is the best way to get the result through Java8 function?

I need to filter elements and then sort based on certain column. Post that I would need to find the unique entries based on combination of columns. Since it is file processing, pipe(|) is used as delimiter to denote the column value.

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"

Data first needs to be filtered based on the Active/Inactive status. Then it needs to be sorted based on 4th column. Lastly, the uniqueness needs to be maintained by combining column 1,2,3.

Expected Output =

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

Upvotes: 2

Views: 161

Answers (4)

Scrobot
Scrobot

Reputation: 1981

You can solve your task this way:

Firstly, just create POJO(Plain Old Java Object) and override the toString() method.

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();
    }
}

Then, you should write the parser from string to MarvelPerson. Side note: Carefully, my implementation is pretty basic, and I suppose it should be modified because I may not have foreseen some corner cases.

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;
    }

}

And then your solution:

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());
                });
    }

}

The output to be printed:

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

Upvotes: 0

senjin.hajrulahovic
senjin.hajrulahovic

Reputation: 3191

Creating a model class and parsing the string is the way to go, but if for some reaseon you don't want to do that you can do it this way:

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());

Upvotes: 1

Samuel Philipp
Samuel Philipp

Reputation: 11050

First of all you should create an Object which represents your String data. Something like this:

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);
    }
}

With this you can create a Stream of objects from your Strings and to the filter, sort and distinct operations afterwards:

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);

After the map operation you filter the values by state and sort them by column 4 (value in my case). At the end you collect all the values in a map for the distinct operation. Add all values you need distinction for to the Arrays.asList(). As values the map takes all the original values (Function.identity()). For duplicates we keep the first value ((o1, o2) -> o1) and we are using a LinkedHashMap to keep the order of the items. At the end wee use only the values of the map.

If you need a List instead of a Collection use new ArrayList(result).

The result will be this:

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

Upvotes: 0

Dushyant Tankariya
Dushyant Tankariya

Reputation: 1454

It seems like you're unable to filter while everything is string only. Try this,

create a new model class which can hold your columns. Ex:

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.
}

Now came to your main class where you can play with your code stuff.

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);

Upvotes: 0

Related Questions