Java實(shí)現(xiàn)對(duì)象轉(zhuǎn)CSV格式
介紹
csv全稱(chēng)“Comma-Separated Values”,是一種逗號(hào)分隔值格式的文件,是一種用來(lái)存儲(chǔ)數(shù)據(jù)的純文本格式文件。CSV文件由任意數(shù)目的記錄組成,記錄間以某種換行符分隔;每條記錄由字段組成,字段間的分隔符是其它字符或字符串。
Java對(duì)象轉(zhuǎn)CSV,有現(xiàn)成的工具包,commons-lang3 的ReflectionToStringBuilder 就可以簡(jiǎn)單的解決的對(duì)象轉(zhuǎn)CSV 但是復(fù)雜點(diǎn)的處理還是不行,而且在運(yùn)行速度上,我測(cè)試了下我自己寫(xiě)的,比這個(gè)快多了,1百萬(wàn)條數(shù)據(jù)大約也就2秒左右, 如果對(duì)速度有要求的話(huà),我們可以使用多線(xiàn)程進(jìn)行分割,比如1千萬(wàn)條數(shù)據(jù),那么我開(kāi)10個(gè)線(xiàn)程,1個(gè)線(xiàn)程執(zhí)行100萬(wàn)條數(shù)據(jù),所有線(xiàn)程執(zhí)行完畢后在按照順序拼接到一起,這樣1千萬(wàn)條數(shù)據(jù)也就最多3~5秒執(zhí)行完畢
代碼樣例
package com.file.csv; import com.date.LocalDateUtils; import lombok.Data; import lombok.SneakyThrows; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.function.Function; /** * 對(duì)象轉(zhuǎn)csv格式 * * @describe * 1百萬(wàn)數(shù)據(jù)測(cè)試 2~3秒 * 調(diào)用順序如下(根據(jù)情況自行選擇) * String s = ObjToCSV.create(userDatas) * .fieldsAll() //轉(zhuǎn)換全部列 * .addIncludeFields() //只包含某些列 * .addExcludeFields("roleData") //排除某些列 * .addHead() //添加頭部字段 * .addContent() //一個(gè)對(duì)象(一行) * .addContents() //多個(gè)對(duì)象(多行) * .addEnding((data)->{ //結(jié)尾說(shuō)明 * JSONObject jsonObject = new JSONObject(); * jsonObject.put("count",data.getNumber()); * jsonObject.put("time",data.getCreateDate()); * return jsonObject.toJSONString(); * }) * .ToString(); //結(jié)果 */ @Data public class ObjToCSV<T> { private String separator = "\u0001|\u0001"; //默認(rèn)分隔符 private StringBuilder str = new StringBuilder(); private T object; private List<T> objects; private List<String> excludeFields = new ArrayList<String>(100) {{ add("serialVersionUID"); }}; private List<String> includeFields = new ArrayList<String>(100); private boolean fieldsAll = false; private int number;//多少行一共 //日期串 20220617204504 private String createDate=LocalDateUtils.getLocalDateTimeStr1() ; private ObjToCSV(T object, String separator) { this.object = object; this.separator = separator; //行數(shù) this.number=1; } private ObjToCSV(T object) { this.object = object; //行數(shù) this.number=1; } private ObjToCSV(List<T> objects) { if (objects.isEmpty()) { throw new NullPointerException("不能是空"); } this.object = objects.get(0); this.objects = objects; //行數(shù) this.number=objects.size(); } private ObjToCSV(List<T> objects, String separator) { if (objects.isEmpty()) { throw new NullPointerException("不能是空"); } this.object = objects.get(0); this.objects = objects; this.separator = separator; //行數(shù) this.number=objects.size(); } // 排除和包含都有,那么以包含的為主 private boolean decideFields(String fieldName) { //包含 if (includeFields.contains(fieldName)) { return false; } //排除 if (excludeFields.contains(fieldName)) { return true; } // 開(kāi)啟全部放行 if (fieldsAll) { return false; } //默認(rèn)攔截全部 return true; } public static <T> ObjToCSV<T> create(T object, String separator) { return new ObjToCSV<T>(object, separator); } public static <T> ObjToCSV<T> create(T object) { return new ObjToCSV<T>(object); } public static <T> ObjToCSV<T> create(List<T> object, String separator) { return new ObjToCSV<T>(object, separator); } public static <T> ObjToCSV<T> create(List<T> object) { return new ObjToCSV<T>(object); } //全部放行 public ObjToCSV<T> fieldsAll() { fieldsAll = true; return this; } //包含 public ObjToCSV<T> addIncludeFields(String... fieldName) { includeFields.addAll(Arrays.asList(fieldName)); return this; } //排除 public ObjToCSV<T> addExcludeFields(String... fieldName) { excludeFields.addAll(Arrays.asList(fieldName)); return this; } //添加頭部 public ObjToCSV<T> addHead() { StringBuilder str1 = new StringBuilder(); Class<?> aClass = this.object.getClass(); Field[] fields = aClass.getDeclaredFields(); int length = fields.length; for (int i = 0; i < length; i++) { Field field = fields[i]; field.setAccessible(true); if (decideFields(field.getName())) { continue; } str1.append(field.getName()).append(separator); } int length1 = separator.length(); String substring = str1.substring(0, str1.length() - length1); this.str.append(substring + "\n"); return this; } //在結(jié)尾補(bǔ)充自定義的描述 public ObjToCSV<T> addEnding(Function<ObjToCSV,String> functor){ String apply = functor.apply( this); this.str.append(apply); return this; } //將對(duì)象轉(zhuǎn)換為CSV格式字符串 @SneakyThrows public ObjToCSV<T> addContent() { StringBuilder str1 = new StringBuilder(); Class<?> aClass = this.object.getClass(); Field[] fields = aClass.getDeclaredFields(); int length = fields.length; for (int i = 0; i < length; i++) { Field field = fields[i]; field.setAccessible(true); if (decideFields(field.getName())) { continue; } Object o = field.get(object); String value = ""; if (o != null) { value = String.valueOf(o); } str1.append(value).append(separator); } int length1 = separator.length(); String substring = str1.substring(0, str1.length() - length1); this.str.append(substring + "\n"); return this; } //將多個(gè)對(duì)象轉(zhuǎn)換為csv格式 public ObjToCSV<T> addContents() { for (T t : this.objects) { this.object=t; addContent(); } return this; } //將結(jié)果輸出為字符串 public String ToString() { return str.toString(); } }
測(cè)試樣例
package com.file; import com.alibaba.fastjson.JSONObject; import com.data.RandomUserData; import com.entity.UserData; import com.file.csv.ObjToCSV; import com.file.csv.ObjToCSV; import com.function.impl.CodeStartAndStopTimeUtil; import lombok.SneakyThrows; import org.junit.Test; import java.util.List; public class ObjToCSVTest { //單個(gè)對(duì)象 @Test public void show1(){ UserData userOne = RandomUserData.getUserOne(); String s = ObjToCSV.create(userOne) .fieldsAll() // .addIncludeFields() .addExcludeFields("roleData") // .addHead() .addContent() // .addContents() .addEnding((data)->{ JSONObject jsonObject = new JSONObject(); jsonObject.put("count",data.getNumber()); jsonObject.put("time",data.getCreateDate()); jsonObject.put("separator",data.getSeparator()); return jsonObject.toJSONString(); }) .ToString(); System.out.println(s); } //多個(gè)對(duì)象,可以使用自定義分隔符 @Test public void show2(){ UserData userOne = RandomUserData.getUserOne(); String s = ObjToCSV.create(userOne,"|") .fieldsAll() .addExcludeFields("roleData") .addContent() .addEnding((data)->{ JSONObject jsonObject = new JSONObject(); jsonObject.put("count",data.getNumber()); jsonObject.put("time",data.getCreateDate()); jsonObject.put("separator",data.getSeparator()); return jsonObject.toJSONString(); }) .ToString(); System.out.println(s); } //排除不顯示的,其他都顯示 @Test public void show3(){ List<UserData> userDatas = RandomUserData.getUserDatas(10); String s = ObjToCSV.create(userDatas,"|") .fieldsAll()//顯示全部字段 .addExcludeFields("roleData")//排除指定字段 .addHead() .addContents() .addEnding((data)->{ JSONObject jsonObject = new JSONObject(); jsonObject.put("count",data.getNumber()); jsonObject.put("time",data.getCreateDate()); jsonObject.put("separator",data.getSeparator()); return jsonObject.toJSONString(); }) .ToString(); System.out.println(s); } //只包含指定字段 ,其他都不顯示 @Test public void show4(){ List<UserData> userDatas = RandomUserData.getUserDatas(10); String s = ObjToCSV.create(userDatas,"|") .addIncludeFields("id","name") .addHead() //添加頭部 .addContents() //添加內(nèi)容 .addEnding((data)->{ //添加結(jié)尾信息 JSONObject jsonObject = new JSONObject(); jsonObject.put("count",data.getNumber()); jsonObject.put("time",data.getCreateDate()); jsonObject.put("separator",data.getSeparator()); return jsonObject.toJSONString(); }) .ToString(); System.out.println(s); } //內(nèi)容 @Test public void show5(){ List<UserData> userDatas = RandomUserData.getUserDatas(10); String s = ObjToCSV.create(userDatas,"|") .fieldsAll() .addExcludeFields("roleData")//排除指定字段 .addContents() //添加內(nèi)容 .ToString(); System.out.println(s); } @SneakyThrows public static void main(String[] args) { List<UserData> userDatas = RandomUserData.getUserDatas(100); String s = ObjToCSV.create(userDatas) .fieldsAll() // .addIncludeFields() .addExcludeFields("roleData") // .addHead() // .addContent() .addContents() .addEnding((data)->{ JSONObject jsonObject = new JSONObject(); jsonObject.put("count",data.getNumber()); jsonObject.put("time",data.getCreateDate()); return jsonObject.toJSONString(); }) .ToString(); System.out.println(s); } }
到此這篇關(guān)于Java實(shí)現(xiàn)對(duì)象轉(zhuǎn)CSV格式的文章就介紹到這了,更多相關(guān)Java對(duì)象轉(zhuǎn)CSV內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot+Ajax+redis實(shí)現(xiàn)隱藏重要接口地址的方法
這篇文章主要介紹了SpringBoot+Ajax+redis實(shí)現(xiàn)隱藏重要接口地址,本篇文章主要講訴使用SpringBoot項(xiàng)目配合Ajax和redis實(shí)現(xiàn)隱藏重要接口地址,這里我以隱藏秒殺地址為例,需要的朋友可以參考下2024-03-03Java中字符串String的+和+=及循環(huán)操作String原理詳解
Java編譯器在編譯時(shí)對(duì)String的+和+=操作會(huì)創(chuàng)建StringBuilder對(duì)象來(lái)進(jìn)行字符串的拼接,下面這篇文章主要給大家介紹了關(guān)于Java中字符串String的+和+=及循環(huán)操作String原理的相關(guān)資料,需要的朋友可以參考下2023-01-01解決Java中socket使用getInputStream()阻塞問(wèn)題
這篇文章主要介紹了解決Java中socket使用getInputStream()阻塞問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12java反射之通過(guò)反射了解集合泛型的本質(zhì)(詳解)
下面小編就為大家?guī)?lái)一篇java反射之通過(guò)反射了解集合泛型的本質(zhì)(詳解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-06-06詳解java中的互斥鎖信號(hào)量和多線(xiàn)程等待機(jī)制
這篇文章主要介紹了Java編程中的互斥鎖,信號(hào)量和多線(xiàn)程等待機(jī)制實(shí)例詳解,簡(jiǎn)單介紹了互斥鎖和信號(hào)量的區(qū)別,需要的朋友可以了解下。2017-09-09java如何通過(guò)FileOutputStream字節(jié)流向文件中寫(xiě)數(shù)據(jù)
這篇文章主要介紹了java如何通過(guò)FileOutputStream字節(jié)流向文件中寫(xiě)數(shù)據(jù)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12