目录
有时为了统计的需要,需要将数据进行行转列,在数据库中一般用CASE WHEN语句来解决,但无法生成生成列标题,如果遇到想动态生成列的情况,用CASE WHEN便不是那么好处理了
正好最近我的一个个人小项目中遇到了这个问题,需要根据数据动态生成列标题,同时数据量不多,便想到自己写一个JAVA版通用的数据行转列的工具类
show me the code
本人写的工具类代码如下:
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
/**
* 行转列工具类
* created on 2020/4/1 9:47
*
* @author puhaiyang
*/
public class RowConvertColUtil {
private static final String NULL_VALUE = "";
private static final String HEADER_NULL_VALUE = "";
private static Set<Object> headerSet;
private static Set<Object> firstColSet;
private RowConvertColUtil() {
}
public static class ConvertData {
private Set<Object> headerSet;
private Set<Object> firstColSet;
private List<List<Object>> dataList;
public ConvertData(List<List<Object>> dataList, Set<Object> headerSet, Set<Object> firstColSet) {
this.headerSet = headerSet;
this.firstColSet = firstColSet;
this.dataList = dataList;
}
public Set<Object> getHeaderSet() {
return headerSet;
}
public void setHeaderSet(Set<Object> headerSet) {
this.headerSet = headerSet;
}
public Set<Object> getFirstColSet() {
return firstColSet;
}
public void setFirstColSet(Set<Object> firstColSet) {
this.firstColSet = firstColSet;
}
public List<List<Object>> getDataList() {
return dataList;
}
public void setDataList(List<List<Object>> dataList) {
this.dataList = dataList;
}
}
/**
* 行转列,返回ConvertData
*
* @param orignalList 原始list
* @param headerName 列表头字段名
* @param firstColName 首列字段名
* @param valueFiedName 值列的字段名
* @param needHeader 是否需要返回列表头
* @return ConvertData
*/
public static synchronized ConvertData doConvertReturnObj(List orignalList, String headerName, String firstColName, String valueFiedName, boolean needHeader) throws Exception {
List<List<Object>> lists = doConvert(orignalList, headerName, firstColName, valueFiedName, needHeader);
return new ConvertData(lists, headerSet, firstColSet);
}
/**
* 行转列,返回转换后的list
*
* @param orignalList 原始list
* @param headerName 列表头字段名
* @param firstColName 首列字段名
* @param valueFiedName 值列的字段名
* @param needHeader 是否需要返回列表头
*/
public static synchronized List<List<Object>> doConvert(List orignalList, String headerName, String firstColName, String valueFiedName, boolean needHeader) throws Exception {
headerSet = new LinkedHashSet<>();
firstColSet = new LinkedHashSet<>();
List<List<Object>> resultList = new ArrayList<>();
getHeaderFirstcolSet(orignalList, headerName, firstColName);
if (needHeader) {
List<Object> headerList = new ArrayList<>();
//填充进header
headerList.add(HEADER_NULL_VALUE);
headerList.addAll(headerSet);
resultList.add(headerList);
}
for (Object firstColNameItem : firstColSet) {
List<Object> colList = new ArrayList<>();
//名称
colList.add(firstColNameItem);
for (Object headerItem : headerSet) {
boolean flag = true;
for (Object orignalObjectItem : orignalList) {
Field headerField = orignalObjectItem.getClass().getDeclaredField(headerName);
headerField.setAccessible(true);
Field firstColField = orignalObjectItem.getClass().getDeclaredField(firstColName);
firstColField.setAccessible(true);
Field valueField = orignalObjectItem.getClass().getDeclaredField(valueFiedName);
valueField.setAccessible(true);
if (headerItem.equals(headerField.get(orignalObjectItem))) {
if (firstColNameItem.equals(firstColField.get(orignalObjectItem))) {
colList.add(valueField.get(orignalObjectItem));
flag = false;
break;
}
}
}
if (flag) {
colList.add(NULL_VALUE);
}
}
resultList.add(colList);
}
return resultList;
}
private static void getHeaderFirstcolSet(List orignalList, String headerName, String firstColName) {
try {
for (Object item : orignalList) {
Field headerField = item.getClass().getDeclaredField(headerName);
headerField.setAccessible(true);
Field firstColField = item.getClass().getDeclaredField(firstColName);
firstColField.setAccessible(true);
headerSet.add(headerField.get(item));
firstColSet.add(firstColField.get(item));
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
代码量不多,短短几十行。
使用方法
调用doConvert或doConvertReturnObj方法
测试代码
再写一个测试代码:
import java.util.*;
/**
* 行转为列测试
* created on 2020/4/1 9:47
*
* @author puhaiyang
*/
public class RowConvertCol {
private static class ScoreInfo {
private String stuName;
private String subjectName;
private Integer value;
public String getStuName() {
return stuName;
}
public String getSubjectName() {
return subjectName;
}
public Integer getValue() {
return value;
}
public ScoreInfo(String stuName, String subjectName, Integer value) {
this.stuName = stuName;
this.subjectName = subjectName;
this.value = value;
}
@Override
public String toString() {
return "ScoreInfo{" +
"stuName='" + stuName + '\'' +
", subjectName='" + subjectName + '\'' +
", value=" + value +
'}';
}
}
public static void main(String[] args) throws Exception {
func2();
}
private static void func2() throws Exception {
List<ScoreInfo> scoreInfoList = new ArrayList<>();
scoreInfoList.add(new ScoreInfo("张三", "语文", 61));
scoreInfoList.add(new ScoreInfo("张三", "数学", 78));
scoreInfoList.add(new ScoreInfo("张三", "英语", 93));
scoreInfoList.add(new ScoreInfo("李四", "语文", 70));
scoreInfoList.add(new ScoreInfo("李四", "数学", 86));
scoreInfoList.add(new ScoreInfo("李四", "英语", 72));
scoreInfoList.add(new ScoreInfo("王五", "语文", 66));
scoreInfoList.add(new ScoreInfo("赵六", "语文", 91));
scoreInfoList.add(new ScoreInfo("王五", "数学", 88));
scoreInfoList.add(new ScoreInfo("赵六", "数学", 63));
scoreInfoList.add(new ScoreInfo("王五", "英语", 93));
scoreInfoList.add(new ScoreInfo("赵六", "英语", 58));
scoreInfoList.add(new ScoreInfo("王七", "英语", 65));
scoreInfoList.add(new ScoreInfo("王七", "数学", 91));
for (ScoreInfo scoreInfo : scoreInfoList) {
System.out.println(scoreInfo.toString());
}
System.out.println("-------------------");
List<List<Object>> lists = RowConvertColUtil.doConvert(scoreInfoList, "subjectName", "stuName", "value", true);
for (List<Object> list : lists) {
System.out.println(list.toString());
}
}
}
测试输出内容:
ScoreInfo{stuName='张三', subjectName='语文', value=61}
ScoreInfo{stuName='张三', subjectName='数学', value=78}
ScoreInfo{stuName='张三', subjectName='英语', value=93}
ScoreInfo{stuName='李四', subjectName='语文', value=70}
ScoreInfo{stuName='李四', subjectName='数学', value=86}
ScoreInfo{stuName='李四', subjectName='英语', value=72}
ScoreInfo{stuName='王五', subjectName='语文', value=66}
ScoreInfo{stuName='赵六', subjectName='语文', value=91}
ScoreInfo{stuName='王五', subjectName='数学', value=88}
ScoreInfo{stuName='赵六', subjectName='数学', value=63}
ScoreInfo{stuName='王五', subjectName='英语', value=93}
ScoreInfo{stuName='赵六', subjectName='英语', value=58}
ScoreInfo{stuName='王七', subjectName='英语', value=65}
ScoreInfo{stuName='王七', subjectName='数学', value=91}
-------------------
[, 语文, 数学, 英语]
[张三, 61, 78, 93]
[李四, 70, 86, 72]
[王五, 66, 88, 93]
[赵六, 91, 63, 58]
[王七, , 91, 65]
希望能有用