Reputation: 39
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
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
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
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
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