目錄
有時爲了統計的需要,需要將數據進行行轉列,在數據庫中一般用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]
希望能有用