需求
下载用户筛选后生成的动态表格,有很多表格需要下载,但是含有不用表格数据的类是不一样的(一个类包含表格的一行数据),希望抽象一个方法出来可以兼容不同类,也就是让类变成一个方法的参数,然后通过传入的不同类参数就能实现将该类中的属性拼接成一行并写入文件。
实体类示例如下
@Data
public class BrowseResultVO implements Serializable {
private static final long serialVersionUID = -2154618191471724836L;
private String sbCancerId;
private String geneSymbol;
private String analysisId;
private String chr;
private String tissueCancer;
private Integer sexBias;
private Integer sbGeneType;
private Integer survivalRelated;
private Integer chemotherapyResponse;
private Integer immunotherapyResponse;
private Integer immuneInfiltration;
public String combineProperty() {
String sbcancerId = StringUtils.hasText(this.getSbCancerId()) ? this.getSbCancerId() : "-";
String geneSymbol = StringUtils.hasText(this.getGeneSymbol()) ? this.getGeneSymbol() : "-";
String analysisId = StringUtils.hasText(this.getAnalysisId()) ? this.getAnalysisId() : "-";
String chr = StringUtils.hasText(this.getChr()) ? this.getChr() : "-";
String tissueCancer = StringUtils.hasText(this.getTissueCancer()) ? this.getTissueCancer() : "-";
String sexBias;
switch (this.getSexBias()) {
case 1:
sexBias = "male selection";
break;
case 2:
sexBias = "female selection";
break;
default:
sexBias = "-";
break;
}
String geneType = SbGeneTypeEnum.getProperty(this.getSbGeneType()) != null ? SbGeneTypeEnum.getProperty(this.getSbGeneType()) : "-";
String survivalRelated = "-";
if (this.getSurvivalRelated() != null) {
survivalRelated = this.getSurvivalRelated() == 1 ? "true" : "false";
}
String chemotherapyResponse = "-";
if (this.getChemotherapyResponse() != null) {
chemotherapyResponse = this.getChemotherapyResponse() == 1 ? "true" : "false";
}
String immunotherapyResponse = "-";
if (this.getImmunotherapyResponse() != null) {
immunotherapyResponse = this.getImmunotherapyResponse() == 1 ? "true" : "false";
}
String immuneInfiltration = "-";
if (this.getImmuneInfiltration() != null) {
immuneInfiltration = this.getImmuneInfiltration() == 1 ? "true" : "false";
}
return sbcancerId + "\t" + geneSymbol + "\t" + analysisId + "\t" + chr + "\t" + tissueCancer + "\t" + sexBias + "\t" + geneType + "\t"
+ survivalRelated + "\t" + chemotherapyResponse + "\t" + immunotherapyResponse + "\t" + immuneInfiltration;
}
第一种方法
采用泛型+反射的方法 (但是反射有效率低的问题)
给每个包含要写入文件数据的类增加一个组合属性的方法(combineProperty),然后通过反射调用该方法即可,具体如下代码:
/**
* 关闭bufferWriter对象
* @param bw 写对象
*/
public static void close(BufferedWriter bw) {
if (bw != null) {
try {
bw.close();
} catch (IOException e) {
log.error("bufferWriter对象关闭错误!", e);
}
}
}
/**
* 调用每个vo类里面的combineProperty方法将数据写入表格
* @param bw 写对象
* @param headers 表头
* @param clazz 标识传入的vo类
* @param dataVOS 要写数据的对象
* @param <T> 泛型类
* @throws IOException
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
public static <T> void writeDataToFile(BufferedWriter bw, List<String> headers, Class<T> clazz, List<T> dataVOS) throws IOException,
NoSuchMethodException, InvocationTargetException, IllegalAccessException {
String header = String.join("\t", headers);
bw.write(header);
bw.newLine();
for (T dataVO : dataVOS) {
T data = clazz.cast(dataVO);
Method combineProperty = data.getClass().getDeclaredMethod("combineProperty");
String res = (String) combineProperty.invoke(data);
bw.write(res);
bw.newLine();
}
}
// 调用示例
public void getTable() {
bw = new BufferedWriter(new FileWriter(fileName));
// 调用谷歌的guava包
List<String> headers = Lists.newArrayList("Gene Symbol", "Analysis ID", "Chr", "Tissue/Cancer");
IOUtils.writeDataToFile(bw, headers, BrowseResultVO.class, browseResultVOS);
}
第二种方法:抽象父类
// 抽象父类
public abstract class DownloadAbstract {
public abstract String combineProperty();
}
//实体类
@Data
public class BrowseResultVO extends DownloadAbstract implements Serializable {
private static final long serialVersionUID = -2154618191471724836L;
private String sbCancerId;
private String geneSymbol;
private String analysisId;
private String chr;
private String tissueCancer;
private Integer sexBias;
private Integer sbGeneType;
private Integer survivalRelated;
private Integer chemotherapyResponse;
private Integer immunotherapyResponse;
private Integer immuneInfiltration;
public String combineProperty() {
String sbcancerId = StringUtils.hasText(this.getSbCancerId()) ? this.getSbCancerId() : "-";
String geneSymbol = StringUtils.hasText(this.getGeneSymbol()) ? this.getGeneSymbol() : "-";
String analysisId = StringUtils.hasText(this.getAnalysisId()) ? this.getAnalysisId() : "-";
String chr = StringUtils.hasText(this.getChr()) ? this.getChr() : "-";
String tissueCancer = StringUtils.hasText(this.getTissueCancer()) ? this.getTissueCancer() : "-";
String sexBias;
switch (this.getSexBias()) {
case 1:
sexBias = "male selection";
break;
case 2:
sexBias = "female selection";
break;
default:
sexBias = "-";
break;
}
String geneType = SbGeneTypeEnum.getProperty(this.getSbGeneType()) != null ? SbGeneTypeEnum.getProperty(this.getSbGeneType()) : "-";
String survivalRelated = "-";
if (this.getSurvivalRelated() != null) {
survivalRelated = this.getSurvivalRelated() == 1 ? "true" : "false";
}
String chemotherapyResponse = "-";
if (this.getChemotherapyResponse() != null) {
chemotherapyResponse = this.getChemotherapyResponse() == 1 ? "true" : "false";
}
String immunotherapyResponse = "-";
if (this.getImmunotherapyResponse() != null) {
immunotherapyResponse = this.getImmunotherapyResponse() == 1 ? "true" : "false";
}
String immuneInfiltration = "-";
if (this.getImmuneInfiltration() != null) {
immuneInfiltration = this.getImmuneInfiltration() == 1 ? "true" : "false";
}
return sbcancerId + "\t" + geneSymbol + "\t" + analysisId + "\t" + chr + "\t" + tissueCancer + "\t" + sexBias + "\t" + geneType + "\t"
+ survivalRelated + "\t" + chemotherapyResponse + "\t" + immunotherapyResponse + "\t" + immuneInfiltration;
}
// 调用方法 <T extends DownloadAbstract>比较重要
public static <T extends DownloadAbstract> void writeDataToFile(BufferedWriter bw, List<String> headers, List<T> dataVOS) throws IOException {
String header = String.join("\t", headers);
bw.write(header);
bw.newLine();
for (DownloadAbstract dataVO : dataVOS) {
String res = dataVO.combineProperty();
bw.write(res);
bw.newLine();
}
}
// 调用示例
public void getTable() {
// browseResultVOS 是List<BrowseResultVO>类型
bw = new BufferedWriter(new FileWriter(fileName));
// 调用谷歌的guava包
List<String> headers = Lists.newArrayList("Gene Symbol", "Analysis ID", "Chr", "Tissue/Cancer");
IOUtils.writeDataToFile(bw, headers, browseResultVOS);
}
方法三 使用接口实现
与抽象类类似
/ 接口
public interface Download {
String combineProperty();
}
//实体类
@Data
public class BrowseResultVO implements Serializable,Download {
private static final long serialVersionUID = -2154618191471724836L;
private String sbCancerId;
private String geneSymbol;
private String analysisId;
private String chr;
private String tissueCancer;
private Integer sexBias;
private Integer sbGeneType;
private Integer survivalRelated;
private Integer chemotherapyResponse;
private Integer immunotherapyResponse;
private Integer immuneInfiltration;
public String combineProperty() {
String sbcancerId = StringUtils.hasText(this.getSbCancerId()) ? this.getSbCancerId() : "-";
String geneSymbol = StringUtils.hasText(this.getGeneSymbol()) ? this.getGeneSymbol() : "-";
String analysisId = StringUtils.hasText(this.getAnalysisId()) ? this.getAnalysisId() : "-";
String chr = StringUtils.hasText(this.getChr()) ? this.getChr() : "-";
String tissueCancer = StringUtils.hasText(this.getTissueCancer()) ? this.getTissueCancer() : "-";
String sexBias;
switch (this.getSexBias()) {
case 1:
sexBias = "male selection";
break;
case 2:
sexBias = "female selection";
break;
default:
sexBias = "-";
break;
}
String geneType = SbGeneTypeEnum.getProperty(this.getSbGeneType()) != null ? SbGeneTypeEnum.getProperty(this.getSbGeneType()) : "-";
String survivalRelated = "-";
if (this.getSurvivalRelated() != null) {
survivalRelated = this.getSurvivalRelated() == 1 ? "true" : "false";
}
String chemotherapyResponse = "-";
if (this.getChemotherapyResponse() != null) {
chemotherapyResponse = this.getChemotherapyResponse() == 1 ? "true" : "false";
}
String immunotherapyResponse = "-";
if (this.getImmunotherapyResponse() != null) {
immunotherapyResponse = this.getImmunotherapyResponse() == 1 ? "true" : "false";
}
String immuneInfiltration = "-";
if (this.getImmuneInfiltration() != null) {
immuneInfiltration = this.getImmuneInfiltration() == 1 ? "true" : "false";
}
return sbcancerId + "\t" + geneSymbol + "\t" + analysisId + "\t" + chr + "\t" + tissueCancer + "\t" + sexBias + "\t" + geneType + "\t"
+ survivalRelated + "\t" + chemotherapyResponse + "\t" + immunotherapyResponse + "\t" + immuneInfiltration;
}
// 方法封装 <T extends Download>比较重要 这里的extends表示的是绑定不是继承,所以后面可以是接口 也可以是类
public static <T extends Download> void writeDataToFile(BufferedWriter bw, List<String> headers, List<T> dataVOS) throws IOException {
String header = String.join("\t", headers);
bw.write(header);
bw.newLine();
for (Download dataVO : dataVOS) {
String res = dataVO.combineProperty();
bw.write(res);
bw.newLine();
}
}
// 调用示例
public void getTable() {
// browseResultVOS 是List<BrowseResultVO>类型
bw = new BufferedWriter(new FileWriter(fileName));
// 调用谷歌的guava包
List<String> headers = Lists.newArrayList("Gene Symbol", "Analysis ID", "Chr", "Tissue/Cancer");
IOUtils.writeDataToFile(bw, headers, browseResultVOS);
}
收获:
感觉抽象类和接口有很多共同点,以及泛型中extends的真实含义。