I have following case.
Given table:
@Getter
@Setter
@AllArgConstructor
class OldRow {
String type;
String name;
int number;
}
List<OldRow> oldTable
type | Name | Number |
---|---|---|
7 | Alex | 15 |
8 | Alex | 17 |
9 | Alex | 15 |
7 | John | 33 |
8 | John | 44 |
9 | John | 54 |
Need to translate it to following structure using java 11
@Getter
@Setter
@AllArgConstructor
class NewRow {
String Name;
int type7;
int type8;
int type9;
}
List<NewRow> newTable
Name | type7 | type8 | type9 |
---|---|---|---|
Alex | 15 | 17 | 15 |
John | 33 | 44 | 54 |
Thank you
CodePudding user response:
Before giving you a way to do it, I want to emphasize a few cosmetic errors I see in your code.
Your java variable names should start with lower-case letters, and names with capital first letters are used for Class namings.
You should indent your code properly so that you (and other readers) can see the code blocks better
I couldn't find an elegant solution with fewer lines, so someone might post it in the future but this will work for you. I will first share the code, and then explain the solution below.
@Getter
@Setter
@AllArgConstructor
class OldRow {
String type;
String name;
int number;
}
@Getter
@Setter
@AllArgConstructor
class NewRow {
String name;
int type7;
int type8;
int type9;
public void printPretty() {
System.out.println(this.name " " this.type7 " " this.type8 " " this.type9);
}
}
public class MainClass {
public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Set<Object> seen = ConcurrentHashMap.newKeySet();
return t -> seen.add(keyExtractor.apply(t));
}
public static void main(String args[]) {
List<OldRow> oldRows = new ArrayList<>();
oldRows.add(new OldRow("8","Alex",17));
oldRows.add(new OldRow("7","Alex",15));
oldRows.add(new OldRow("9","Alex",15));
oldRows.add(new OldRow("7","John",33));
oldRows.add(new OldRow("8","John",44));
oldRows.add(new OldRow("9","John",54));
Map<String,Integer> type7Map = new HashMap<>();
Map<String,Integer> type8Map = new HashMap<>();
Map<String,Integer> type9Map = new HashMap<>();
oldRows.forEach(oldRow -> {
if(oldRow.type.equals("7"))
type7Map.put(oldRow.getName(), oldRow.getNumber());
if(oldRow.type.equals("8"))
type8Map.put(oldRow.getName(), oldRow.getNumber());
if(oldRow.type.equals("9"))
type9Map.put(oldRow.getName(), oldRow.getNumber());
});
List<NewRow> newRows = oldRows.stream()
.filter(distinctByKey(OldRow::getName))
.map(oldRow -> new NewRow(
oldRow.name,
type7Map.get(oldRow.getName()),
type8Map.get(oldRow.getName()),
type9Map.get(oldRow.getName())
))
.collect(Collectors.toList());
for(NewRow newRow : newRows) {
newRow.printPretty();
}
}
}
The first part of the main is to create the OldRow
instances you have in your example. Then 3 maps are created to keep type7, type8, and type9 values for each name. Since you only have these 3 types; we can use a static number of maps.
These maps are filled by iterating over the oldRows
list, then NewRow
entities are filled into a new array by streaming the oldRows
list and looking up type values from maps.
Finally, the print statements, so that you can see what is the last state of the newRows
array.