将Java列表转换为Pivot格式
我有一个下面的类,希望用java将数据对象列表转换为透视表格式将Java列表转换为Pivot格式,java,data-structures,java-8,java-stream,Java,Data Structures,Java 8,Java Stream,我有一个下面的类,希望用java将数据对象列表转换为透视表格式 public class Data { private String consultedOn; private String consultedBy; // Getters // Setters } List<Data> reports = new ArrayList<Data>(); reports.add(new Data("04/12/2018","Mr.
public class Data {
private String consultedOn;
private String consultedBy;
// Getters
// Setters
}
List<Data> reports = new ArrayList<Data>();
reports.add(new Data("04/12/2018","Mr.Bob"));
reports.add(new Data("04/12/2018","Mr.Jhon"));
reports.add(new Data("04/12/2018","Mr.Bob"));
reports.add(new Data("05/12/2018","Mr.Jhon"));
reports.add(new Data("06/12/2018","Mr.Bob"));
reports.add(new Data("06/12/2018","Mr.Jhon"));
reports.add(new Data("07/12/2018","Mr.Bob"));
请注意,consultedOn字段不限于两个值,此字段可能包含任何数据,因此集合应该是动态的
我试着在下面的代码中使用Java8流
class DataMap {
private String consultedOn;
private String consultedBy;
public DataMap(String consultedOn) {
super();
this.consultedOn = consultedOn;
}
public DataMap(String consultedOn, String consultedBy) {
super();
this.consultedOn = consultedOn;
this.consultedBy = consultedBy;
}
public String getConsultedOn() {
return consultedOn;
}
public void setConsultedOn(String consultedOn) {
this.consultedOn = consultedOn;
}
public String getConsultedBy() {
return consultedBy;
}
public void setConsultedBy(String consultedBy) {
this.consultedBy = consultedBy;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((consultedOn == null) ? 0 : consultedOn.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof DataMap ))
return false;
DataMap other = (DataMap )obj;
if (consultedOn == null) {
if (other.consultedOn != null)
return false;
} else if (!consultedOn.equals(other.consultedOn))
return false;
return true;
}
}
Map<DataMap, List<DataReport>> map = reports.stream()
.collect(Collectors.groupingBy(x -> new DataMap(x.getConsultedOn(), x.getConsultedBy())));
类数据映射{
私人字符串咨询;
私人字符串咨询人;
公共数据映射(字符串参考){
超级();
this.consultedOn=consultedOn;
}
公共数据映射(字符串consultedOn、字符串consultedBy){
超级();
this.consultedOn=consultedOn;
this.consultedBy=consultedBy;
}
公共字符串getConsultedOn(){
回访咨询;
}
公共void setConsultedOn(字符串consultedOn){
this.consultedOn=consultedOn;
}
公共字符串getConsultedBy(){
返回咨询人;
}
公共void setConsultedBy(字符串consultedBy){
this.consultedBy=consultedBy;
}
@凌驾
公共int hashCode(){
最终整数素数=31;
int结果=1;
result=prime*result+((consultedOn==null)?0:consultedOn.hashCode();
返回结果;
}
@凌驾
公共布尔等于(对象obj){
if(this==obj)
返回true;
if(obj==null)
返回false;
如果(!(数据映射的obj实例))
返回false;
DataMap other=(DataMap)obj;
if(consultedOn==null){
if(other.consultedOn!=null)
返回false;
}else如果(!consultedOn.equals(other.consultedOn))
返回false;
返回true;
}
}
Map=reports.stream()
.collect(Collectors.groupingBy(x->newdatamap(x.getConsultedOn(),x.getConsultedBy()));
但是地图并没有按照我的期望给出预期的结果
我不知道如何处理这类数据,如果有任何帮助,我们将不胜感激。这里有一个完整的答案,使用我在评论中解释的技巧,即设计一个类
行
,表示您希望为每一行生成的内容,即consultedOn
字符串,以及每个人的大量咨询
public class Pivot {
private static final class Data {
private final String consultedOn;
private final String consultedBy;
public Data(String consultedOn, String consultedBy) {
this.consultedOn = consultedOn;
this.consultedBy = consultedBy;
}
public String getConsultedOn() {
return consultedOn;
}
public String getConsultedBy() {
return consultedBy;
}
}
private static final class Row {
private final String consultedOn;
private final Map<String, Integer> consultationsByPerson = new HashMap<>();
public Row(String consultedOn) {
this.consultedOn = consultedOn;
}
public void addPerson(String person) {
consultationsByPerson.merge(person, 1, Integer::sum);
}
public int getConsultationsFor(String person) {
return consultationsByPerson.getOrDefault(person, 0);
}
public String getConsultedOn() {
return consultedOn;
}
}
private static class PivotReport {
private final Map<String, Row> rowsByConsultedOn = new HashMap<>();
private SortedSet<String> persons = new TreeSet<>();
private PivotReport() {}
private void addData(Data d) {
rowsByConsultedOn.computeIfAbsent(d.getConsultedOn(), Row::new).addPerson(d.getConsultedBy());
persons.add(d.consultedBy);
}
public static PivotReport create(List<Data> list) {
PivotReport report = new PivotReport();
list.forEach(report::addData);
return report;
}
public String toString() {
String headers = "Consulted on\t" + String.join("\t", persons);
String rows = rowsByConsultedOn.values()
.stream()
.sorted(Comparator.comparing(Row::getConsultedOn))
.map(this::rowToString)
.collect(Collectors.joining("\n"));
return headers + "\n" + rows;
}
private String rowToString(Row row) {
return row.getConsultedOn() + "\t" +
persons.stream()
.map(person -> Integer.toString(row.getConsultationsFor(person)))
.collect(Collectors.joining("\t"));
}
}
public static void main(String[] args) {
List<Data> list = createListOfData();
PivotReport report = PivotReport.create(list);
System.out.println(report);
}
private static List<Data> createListOfData() {
List<Data> reports = new ArrayList<Data>();
reports.add(new Data("04/12/2018","Mr.Bob"));
reports.add(new Data("04/12/2018","Mr.Jhon"));
reports.add(new Data("04/12/2018","Mr.Bob"));
reports.add(new Data("05/12/2018","Mr.Jhon"));
reports.add(new Data("06/12/2018","Mr.Bob"));
reports.add(new Data("06/12/2018","Mr.Jhon"));
reports.add(new Data("07/12/2018","Mr.Bob"));
reports.add(new Data("07/12/2018","Mr.Smith"));
return reports;
}
}
公共类透视{
私有静态最终类数据{
私人最终字符串咨询;
私人最终字符串咨询人;
公共数据(字符串consultedOn、字符串consultedBy){
this.consultedOn=consultedOn;
this.consultedBy=consultedBy;
}
公共字符串getConsultedOn(){
回访咨询;
}
公共字符串getConsultedBy(){
返回咨询人;
}
}
私有静态最终类行{
私人最终字符串咨询;
private final Map consultationsByPerson=new HashMap();
公用行(字符串参考){
this.consultedOn=consultedOn;
}
公共人员(字符串人员){
merge(person,1,Integer::sum);
}
public int GetConsultationfor(字符串人){
返回consultationsByPerson.getOrDefault(person,0);
}
公共字符串getConsultedOn(){
回访咨询;
}
}
私有静态类数据透视报告{
私有最终映射rowsByConsultedOn=newhashmap();
私有分类集人员=新树集();
专用数据透视表(){}
专用void addData(数据d){
rowsByConsultedOn.computeIfAbsent(d.getConsultedOn(),Row::new).addPerson(d.getConsultedBy());
人员。添加(d.咨询人);
}
公共静态数据透视报告创建(列表){
数据透视报告=新数据透视报告();
list.forEach(report::addData);
返回报告;
}
公共字符串toString(){
String headers=“咨询\t”+String.join(“\t”,persons);
String rows=rowsByConsultedOn.values()
.stream()
.sorted(Comparator.comparing(行::getConsultedOn))
.map(this::rowToString)
.collect(收集器.加入(“\n”));
返回标题+“\n”+行;
}
私有字符串rowToString(行){
返回行。getConsultedOn()+“\t”+
人流()
.map(person->Integer.toString(row.getConsultationsFor(person)))
.collect(收集器.连接(“\t”);
}
}
公共静态void main(字符串[]args){
List List=createListOfData();
数据透视报告=数据透视报告。创建(列表);
系统输出打印(报告);
}
私有静态列表createListOfData(){
列表报告=新建ArrayList();
报告。添加(新数据(“2018年12月4日”、“鲍勃先生”);
报告。添加(新数据(“2018年12月4日”,“Jhon先生”);
报告。添加(新数据(“2018年12月4日”、“鲍勃先生”);
报告。添加(新数据(“2018年12月5日”,“Jhon先生”);
报告。添加(新数据(“2018年12月6日”、“鲍勃先生”);
报告。添加(新数据(“2018年12月6日”,“Jhon先生”);
报告。添加(新数据(“2018年12月7日”、“鲍勃先生”);
报告。添加(新数据(“2018年12月7日”、“史密斯先生”);
返回报告;
}
}
请注意,由于您在
consultedOn
字段中使用的是字符串而不是LocalDate,因此日期将按字典顺序排序,而不是按时间顺序排序。您应该使用适当的类型:LocalDate。下面是一个完整的答案,使用我在评论中解释的技巧,即设计一个类行
,表示您希望为每一行生成的内容,即一个consultedOn
字符串,以及每个人的一些咨询
public class Pivot {
private static final class Data {
private final String consultedOn;
private final String consultedBy;
public Data(String consultedOn, String consultedBy) {
this.consultedOn = consultedOn;
this.consultedBy = consultedBy;
}
public String getConsultedOn() {
return consultedOn;
}
public String getConsultedBy() {
return consultedBy;
}
}
private static final class Row {
private final String consultedOn;
private final Map<String, Integer> consultationsByPerson = new HashMap<>();
public Row(String consultedOn) {
this.consultedOn = consultedOn;
}
public void addPerson(String person) {
consultationsByPerson.merge(person, 1, Integer::sum);
}
public int getConsultationsFor(String person) {
return consultationsByPerson.getOrDefault(person, 0);
}
public String getConsultedOn() {
return consultedOn;
}
}
private static class PivotReport {
private final Map<String, Row> rowsByConsultedOn = new HashMap<>();
private SortedSet<String> persons = new TreeSet<>();
private PivotReport() {}
private void addData(Data d) {
rowsByConsultedOn.computeIfAbsent(d.getConsultedOn(), Row::new).addPerson(d.getConsultedBy());
persons.add(d.consultedBy);
}
public static PivotReport create(List<Data> list) {
PivotReport report = new PivotReport();
list.forEach(report::addData);
return report;
}
public String toString() {
String headers = "Consulted on\t" + String.join("\t", persons);
String rows = rowsByConsultedOn.values()
.stream()
.sorted(Comparator.comparing(Row::getConsultedOn))
.map(this::rowToString)
.collect(Collectors.joining("\n"));
return headers + "\n" + rows;
}
private String rowToString(Row row) {
return row.getConsultedOn() + "\t" +
persons.stream()
.map(person -> Integer.toString(row.getConsultationsFor(person)))
.collect(Collectors.joining("\t"));
}
}
public static void main(String[] args) {
List<Data> list = createListOfData();
PivotReport report = PivotReport.create(list);
System.out.println(report);
}
private static List<Data> createListOfData() {
List<Data> reports = new ArrayList<Data>();
reports.add(new Data("04/12/2018","Mr.Bob"));
reports.add(new Data("04/12/2018","Mr.Jhon"));
reports.add(new Data("04/12/2018","Mr.Bob"));
reports.add(new Data("05/12/2018","Mr.Jhon"));
reports.add(new Data("06/12/2018","Mr.Bob"));
reports.add(new Data("06/12/2018","Mr.Jhon"));
reports.add(new Data("07/12/2018","Mr.Bob"));
reports.add(new Data("07/12/2018","Mr.Smith"));
return reports;
}
}
公共类Pivo
Map<Pair<String, String>, Integer> map = reports
.stream()
.collect(toMap(data -> new Pair<>(data.getConsultedOn(),
data.getConsultedBy()), data -> 1, Integer::sum));
Map<String, DataMap> result= new HashMap<>();
class DataMap {
private String consultedOn;
private Map<String, Integer> map;
}
Set<String> persons = new HashSet<>();
persons = reports.stream().map(Data::getConsultedBy).collect(Collectors.toSet());
for (Map.Entry<Pair<String, String>, Integer> entry : map.entrySet()) {
Map<String, Integer> val = new HashMap<>();
for (String person : persons) {
if (!person.equals(entry.getKey().getValue()))
val.put(person, 0);
else
val.put(entry.getKey().getValue(), entry.getValue());
}
result.put(entry.getKey().getKey(), new DataMap(entry.getKey().getKey(), val));
}
List<DataMap> finalResult = new ArrayList<>(result.values());
public class Application {
Set<String> doctors = new LinkedHashSet<>();
private void addDataToReport(Map<String, List<String>> reportMap, String consultedOn, String consultedBy) {
doctors.add(consultedBy); // set the doctors Set
reportMap.merge(consultedOn, Arrays.asList(consultedBy)// if key = consultedOn is not there add , a new list
, (v1, v2) -> Stream.concat(v1.stream(), v2.stream()).collect(Collectors.toList()));//else merge previous and new values , here concatenate two lists
}
private void printReport(Map<String, List<String>> reportMap) {
/*Set Headers*/
String formatting = "%10s";//give a block of 10 characters for each string to print
System.out.format(formatting, "consultedOn");
doctors.forEach(t -> System.out.format(formatting, t));// print data on console without an implicit new line
System.out.println("\n---------------------------------------");
/*Set row values*/
for (Map.Entry<String, List<String>> entry : reportMap.entrySet()) {
Map<String, Integer> map = new LinkedHashMap<>();
doctors.forEach(t -> map.put(t, 0)); // initialise each doctor count on a day to 0
entry.getValue().forEach(t -> map.put(t, map.get(t) + 1));
System.out.format(formatting, entry.getKey());
map.values().forEach(t -> System.out.format(formatting, t));
System.out.println();
}
}
public static void main(String[] args) {
Application application = new Application();
Map<String, List<String>> reportMap = new LinkedHashMap<>();
String MR_JHON = "Mr.Jhon";
String MR_BOB = "Mr.Bob ";
application.addDataToReport(reportMap, "04/12/2018", MR_BOB);
application.addDataToReport(reportMap, "04/12/2018", MR_JHON);
application.addDataToReport(reportMap, "04/12/2018", MR_BOB);
application.addDataToReport(reportMap, "05/12/2018", MR_JHON);
application.addDataToReport(reportMap, "06/12/2018", MR_BOB);
application.addDataToReport(reportMap, "06/12/2018", MR_JHON);
application.addDataToReport(reportMap, "07/12/2018", MR_BOB);
application.printReport(reportMap);
}
}
consultedOn Mr.Bob Mr.Jhon
---------------------------------------
04/12/2018 2 1
05/12/2018 0 1
06/12/2018 1 1
07/12/2018 1 0
Map<String, Map<String, Long>> finalMapping = reports.stream()
.collect(Collectors.groupingBy(DataMap::getConsultedOn,
Collectors.groupingBy(DataMap::getConsultedBy,Collectors.counting())));
{05/12/2018={Mr.Jhon=1}, 06/12/2018={Mr.Jhon=1, Mr.Bob=1},
07/12/2018={Mr.Bob=1}, 04/12/2018={Mr.Jhon=1, Mr.Bob=2}}
Set<String> consultedBys = reports.stream()
.map(DataMap::getConsultedBy)
.collect(Collectors.toSet());
finalMapping.forEach((k, v) -> consultedBys.forEach(c -> v.putIfAbsent(c, 0L)));
{05/12/2018={Mr.Jhon=1, Mr.Bob=0}, 06/12/2018={Mr.Jhon=1, Mr.Bob=1},
07/12/2018={Mr.Jhon=0, Mr.Bob=1}, 04/12/2018={Mr.Jhon=1, Mr.Bob=2}}