Java中List集合數(shù)據(jù)修改方式
Java中List集合數(shù)據(jù)修改
先說寫這篇文章的原因
我被提供了一個需求,Excel表格數(shù)據(jù)導(dǎo)入數(shù)據(jù)庫,按照常理而言是很簡單的,但是這個需求不那么簡單,Excel表格里面的字段和數(shù)據(jù)庫不統(tǒng)一,甚至多與實體類的屬性數(shù)量,而且要實現(xiàn)用戶自由選擇Excel表格某列對應(yīng)數(shù)據(jù)庫某個字段,聽到這個需求我真的是被整懵逼了?。?!
先說一下我的思路,首先,我個人感覺不可能將Excel表格全部讀出來(數(shù)據(jù)類型無法統(tǒng)一;不知道列數(shù)量;選擇的列比較少的話,效率慢死;)所以我的想法是按照列讀取數(shù)據(jù)(我認(rèn)為Excel數(shù)據(jù)讀取都是要遍歷一遍二維數(shù)組,按行按列于操作Excel效率沒什么區(qū)別)
為了方便,我寫的讀取Excel的工具類返回的是Map類型數(shù)據(jù),map里面放入List集合,通過返回的List集合獲取數(shù)據(jù),這樣我就可以獲取很多類型的數(shù)據(jù)而不必局限于返回值類型
這里是我循環(huán)賦值的語句
public Map<String, Object> importSQL(@RequestBody String c, HttpServletRequest request) throws Exception {
? ? java.util.Map<String, Object> map = new HashMap<>();
? ? java.util.Map<String, Object> poiMap = new HashMap<>();
? ? // 對Excel表格操作的工具類
? ? PoiExcel poiExcel = new PoiExcel();
? ? // 保存從Excel讀取出來信息
? ? List<Attendance> attList = new ArrayList<Attendance>();
? ? List<String> string = new ArrayList<String>();
? ? Attendance att = new Attendance();
? ? try {
? ? ? ? List<Relation> relationList = new ArrayList<Relation>();
? ? ? ? JSONObject strj = new JSONObject(c);
? ? ? ? // 獲取讀取Excel表格開始行數(shù)
? ? ? ? int startRow = strj.getInt("start");
? ? ? ? // 獲取用戶自定義匹配數(shù)據(jù)
? ? ? ? String json = strj.getJSONArray("matchData").toString();
? ? ? ? // 獲取用戶上傳excel表格保存路徑
? ? ? ? String filePath = strj.getString("filePath");
? ? ? ? filePath = "1230.xls";
? ? ? ? // 將用戶自定義匹配數(shù)據(jù)放入relationList中,便于取值
? ? ? ? relationList = com.alibaba.fastjson.JSONArray.parseArray(json, Relation.class);
? ? ? ? /**
? ? ? ? ?* 測試使用
? ? ? ? ?*/
? ? ? ? for (int i = 0; i < relationList.size(); i++) {
? ? ? ? ? ? System.out.println("第"+i+"次執(zhí)行");
? ? ? ? ? ? /**
? ? ? ? ? ? ?* 匹配查詢 filePath:文件名字 startRow:開始查詢行數(shù)
? ? ? ? ? ? ?* relationList.get(i).getColumnNum():查詢列值
? ? ? ? ? ? ?* 返回map類型數(shù)據(jù),數(shù)據(jù)類型多樣,統(tǒng)一返回值 返回值是List類型數(shù)據(jù),工具類中暫時只有一個String類型,測試使用
? ? ? ? ? ? ?*/
? ? ? ? ? ? string = (List<String>) poiExcel.ExcelRead(filePath, startRow, relationList.get(i).getColumnNum())
? ? ? ? ? ? ? ? ? ? .get("list");
? ? ? ? ? ? // 初始化集合
? ? ? ? ? ? if (i == 0) {
? ? ? ? ? ? ? ? for (int a = 0; a < string.size(); a++) {
? ? ? ? ? ? ? ? ? ? attList.add(att);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? if (relationList.get(i).getDescribe().equals("學(xué)號")) {
? ? ? ? ? ? ? ? System.out.println("學(xué)號");
? ? ? ? ? ? ? ? // 循環(huán)賦值
? ? ? ? ? ? ? ? for (int j = 0; j < string.size(); j++) {
? ? ? ? ? ? ? ? ? ? attList.get(j).setStuid(string.get(j));
? ? ? ? ? ? ? ? }
? ? ? ? ? ? } else if (relationList.get(i).getDescribe().equals("姓名")) {
? ? ? ? ? ? ? ? System.out.println("姓名");
? ? ? ? ? ? ? ? // 循環(huán)賦值
? ? ? ? ? ? ? ? for (int j = 0; j < string.size(); j++) {
? ? ? ? ? ? ? ? ? ? attList.get(j).setName(string.get(j));
? ? ? ? ? ? ? ? }
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? System.out.println("分?jǐn)?shù)");
? ? ? ? ? ? ? ? for (int j = 0; j < string.size(); j++) {
? ? ? ? ? ? ? ? ? ? attList.get(j).setScore(Integer.parseInt(string.get(j)));
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? } catch (Exception e) {
? ? ? ? System.out.println(e);
? ? }
? ? /**
? ? ?* 以上為for循環(huán)遍歷Excel表格數(shù)據(jù),以下為測試輸出,遍歷是否正確
? ? ?*/
? ? for (int x = 0; x < attList.size(); x++) {
? ? ? ? System.out.println("讀取Excel表格信息為:" + attList.get(x).toString());
? ? }
? ? return map;
}我的想法是先初始化集合,確定集合size和集合屬性,但是突然出現(xiàn)一個問題就是我遍歷出來的數(shù)據(jù)在循環(huán)賦值的時候attList里面的屬性全部變成最新一次的屬性,然后我就debug調(diào)試,發(fā)現(xiàn)每次賦值前面對應(yīng)的值也都會更改,當(dāng)時腦子里面就冒出了一個念頭:值類型和引用類型傳遞?。。∮谑?,我做了如下更改:
? ? if (i == 0) {
? ? ? ? for (int a = 0; a < string.size(); a++) {
? ? ? ? ? ? Attendance att = new Attendance();
? ? ? ? ? ? attList.add(att);
? ? ? ? }
? ? }將new 對象這句話放到for循環(huán)里面
運行之后值就對了,唉,開發(fā)經(jīng)驗太少,竟然被這種問題困擾了一天
下面是我百度的值類型和引用類型區(qū)別:
引用類型表示你操作的數(shù)據(jù)是同一個,也就是說當(dāng)你傳一個參數(shù)給另一個方法時,你在另一個方法中改變這個變量的值,那么調(diào)用這個方法是傳入的變量的值也將改變.
值類型表示復(fù)制一個當(dāng)前變量傳給方法,當(dāng)你在這個方法中改變這個變量的值時,最初生命的變量的值不會變.
引用傳遞:傳的是地址,就是將實參的地址傳遞給形參,形參改變了,實參當(dāng)然被改變了,因為他們指向相同的地址。
最后,一定要記住,當(dāng)引用一個集合的時候,集合里面有n個對象,這個時候肯定要new n對象,否則,這些對象是引用的同一個?。。?!
Java中List集合的介紹
List 是什么
JavaList集合是指由JavaList接口以及List接口的所有實現(xiàn)類組成的集合。
List集合中的元素允許重復(fù),各元素的順序放是對象插入的順序. 類似Java中的數(shù)組,用戶可通過使用索引(元素在集合中的位置)來訪問集合中的元素.
1.Java集合介紹
Java集合就像一個容器,可以存儲任何類型的數(shù)據(jù),也可以結(jié)合泛型來存儲具體的類型對象。在程序運行時,Java集合可以動態(tài)的進行擴展,隨著元素的增加而擴大。在Java中,集合類通常存在于java.util包中。
Java集合主要由2大體系構(gòu)成,分別是Collection體系和Map體系,其中Collection和Map分別是2大體系中的頂層接口。
Collection主要有三個子接口,分別為List(列表)、Set(集)、Queue(隊列)。其中,List、Queue中的元素有序可重復(fù),而Set中的元素?zé)o序不可重復(fù)。
List中主要有ArrayList、LinkedList兩個實現(xiàn)類;Set中則是有HashSet實現(xiàn)類;而Queue是在JDK1.5后才出現(xiàn)的新集合,主要以數(shù)組和鏈表兩種形式存在。
Map同屬于java.util包中,是集合的一部分,但與Collection是相互獨立的,沒有任何關(guān)系。Map中都是以key-value的形式存在,其中key必須唯一,主要有HashMap、HashTable、treeMap三個實現(xiàn)類。

2.List介紹
在Collection中,List集合是有序的,可對其中每個元素的插入位置進行精確地控制,可以通過索引來訪問元素,遍歷元素。
在List集合中,我們常用到ArrayList和LinkedList這兩個類
2.1 ArrayList集合
- ArrayList底層通過數(shù)組實現(xiàn),隨著元素的增加而動態(tài)擴容。
- ArrayList是Java集合框架中使用最多的一個類,是一個數(shù)組隊列,線程不安全集合。它繼承于AbstractList,實現(xiàn)了List, RandomAccess, Cloneable, Serializable接口。
- ArrayList實現(xiàn)List,得到了List集合框架基礎(chǔ)功能;
- ArrayList實現(xiàn)RandomAccess,獲得了快速隨機訪問存儲元素的功能,RandomAccess是一個標(biāo)記接口,沒有任何方法;
- ArrayList實現(xiàn)Cloneable,得到了clone()方法,可以實現(xiàn)克隆功能;
- ArrayList實現(xiàn)Serializable,表示可以被序列化,通過序列化去傳輸,典型的應(yīng)用就是hessian協(xié)議。
ArrayList集合的特點:
- 容量不固定,隨著容量的增加而動態(tài)擴容(閾值基本不會達到)
- 有序集合(插入的順序==輸出的順序)
- 插入的元素可以為null
- 增刪改查效率更高(相對于LinkedList來說)
- 線程不安全
ArrayList的底層數(shù)據(jù)結(jié)構(gòu):

2.2 LinkedList集合
- LinkedList底層通過鏈表來實現(xiàn),隨著元素的增加不斷向鏈表的后端增加節(jié)點。
- LinkedList是一個雙向鏈表,每一個節(jié)點都擁有指向前后節(jié)點的引用。相比于ArrayList來說,LinkedList的隨機訪問效率更低。它繼承AbstractSequentialList,實現(xiàn)了List, Deque, Cloneable, Serializable接口。
- LinkedList實現(xiàn)List,得到了List集合框架基礎(chǔ)功能;
- LinkedList實現(xiàn)Deque,Deque 是一個雙向隊列,也就是既可以先入先出,又可以先入后出,說簡單點就是既可以在頭部添加元素,也可以在尾部添加元素;
- LinkedList實現(xiàn)Cloneable,得到了clone()方法,可以實現(xiàn)克隆功能;
- LinkedList實現(xiàn)Serializable,表示可以被序列化,通過序列化去傳輸,典型的應(yīng)用就是hessian協(xié)議。
LinkedList集合的底層數(shù)據(jù)結(jié)構(gòu):

3.List常用方法
A:添加功能 boolean add(E e):向集合中添加一個元素 void add(int index, E element):在指定位置添加元素 boolean addAll(Collection<? extends E> c):向集合中添加一個集合的元素。 B:刪除功能 void clear():刪除集合中的所有元素 E remove(int index):根據(jù)指定索引刪除元素,并把刪除的元素返回 boolean remove(Object o):從集合中刪除指定的元素 boolean removeAll(Collection<?> c):從集合中刪除一個指定的集合元素。 C:修改功能 E set(int index, E element):把指定索引位置的元素修改為指定的值,返回修改前的值。 D:獲取功能 E get(int index):獲取指定位置的元素 Iterator iterator():就是用來獲取集合中每一個元素。 E:判斷功能 boolean isEmpty():判斷集合是否為空。 boolean contains(Object o):判斷集合中是否存在指定的元素。 boolean containsAll(Collection<?> c):判斷集合中是否存在指定的一個集合中的元素。 F:長度功能 int size():獲取集合中的元素個數(shù) G:把集合轉(zhuǎn)換成數(shù)組 Object[] toArray():把集合變成數(shù)組。
3.1 ArrayList 基本操作
public class ArrayListTest {
public static void main(String[] agrs){
//創(chuàng)建ArrayList集合:
List<String> list = new ArrayList<String>();
System.out.println("ArrayList集合初始化容量:"+list.size());
// ArrayList集合初始化容量:0
//添加功能:
list.add("Hello");
list.add("world");
list.add(2,"!");
System.out.println("ArrayList當(dāng)前容量:"+list.size());
// ArrayList當(dāng)前容量:3
//修改功能:
list.set(0,"my");
list.set(1,"name");
System.out.println("ArrayList當(dāng)前內(nèi)容:"+list.toString());
// ArrayList當(dāng)前內(nèi)容:[my, name, !]
//獲取功能:
String element = list.get(0);
System.out.println(element);
// my
//迭代器遍歷集合:(ArrayList實際的跌倒器是Itr對象)
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
String next = iterator.next();
System.out.println(next);
}
/**
my
name
!
*/
//for循環(huán)迭代集合:
for(String str:list){
System.out.println(str);
}
/**
my
name
!
*/
//判斷功能:
boolean isEmpty = list.isEmpty();
boolean isContain = list.contains("my");
//長度功能:
int size = list.size();
//把集合轉(zhuǎn)換成數(shù)組:
String[] strArray = list.toArray(new String[]{});
//刪除功能:
list.remove(0);
list.remove("world");
list.clear();
System.out.println("ArrayList當(dāng)前容量:"+list.size());
// ArrayList當(dāng)前容量:0
}
}
3.2 LinkedList 基本操作
public class LinkedListTest {
public static void main(String[] agrs){
List<String> linkedList = new LinkedList<String>();
System.out.println("LinkedList初始容量:"+linkedList.size());
// LinkedList初始容量:0
//添加功能:
linkedList.add("my");
linkedList.add("name");
linkedList.add("is");
linkedList.add("jiaboyan");
System.out.println("LinkedList當(dāng)前容量:"+ linkedList.size());
// LinkedList當(dāng)前容量:4
//修改功能:
linkedList.set(0,"hello");
linkedList.set(1,"world");
System.out.println("LinkedList當(dāng)前內(nèi)容:"+ linkedList.toString());
// LinkedList當(dāng)前內(nèi)容:[hello, world, is, jiaboyan]
//獲取功能:
String element = linkedList.get(0);
System.out.println(element);
// hello
//遍歷集合:(LinkedList實際的迭代器是ListItr對象)
Iterator<String> iterator = linkedList.iterator();
while(iterator.hasNext()){
String next = iterator.next();
System.out.println(next);
}
/**
hello
world
is
jiaboyan
*/
//for循環(huán)迭代集合:
for(String str:linkedList){
System.out.println(str);
}
/**
hello
world
is
jiaboyan
*/
//判斷功能:
boolean isEmpty = linkedList.isEmpty();
boolean isContains = linkedList.contains("jiaboyan");
//長度功能:
int size = linkedList.size();
//刪除功能:
linkedList.remove(0);
linkedList.remove("jiaboyan");
linkedList.clear();
System.out.println("LinkedList當(dāng)前容量:" + linkedList.size());
// LinkedList當(dāng)前容量:0
}
}
4.ArrayList和LinkedList比較
元素新增性能比較
網(wǎng)上很多說的是,在做新增操作時,ArrayList的效率遠不如LinkedList,因為Arraylist底層時數(shù)組實現(xiàn)的,在動態(tài)擴容時,性能會有所損耗,而LinkedList不存在數(shù)組擴容機制,所以LinkedList的新增性能較好。究竟時哪個好呢,我們用實踐得到結(jié)果。
public class ListTest{
// 迭代次數(shù)
public static int ITERATION_NUM = 100000;
public static void main(String[] args) {
try{
insertPerformanceCompare();
}catch (Exception e){}
}
//新增性能比較:
public static void insertPerformanceCompare() throws InterruptedException {
Thread.sleep(5000);
long start = System.nanoTime();
List<Integer> linkedList = new LinkedList<Integer>();
for (int x = 0; x < ITERATION_NUM; x++) {
linkedList.add(x);
}
long end = System.nanoTime();
System.out.println("LinkedList獲取測試開始 " + (end - start));
start = System.nanoTime();
List<Integer> arrayList = new ArrayList<Integer>();
for (int x = 0; x < ITERATION_NUM; x++) {
arrayList.add(x);
}
end = System.nanoTime();
System.out.println("ArrayList獲取測試開始 " + (end - start));
}
}
測試結(jié)果:
第一次:
LinkedList新增測試開始 10873720
ArrayList新增測試開始 5535277
第二次:
LinkedList新增測試開始 13097503
ArrayList新增測試開始 6046139
第三次:
LinkedList新增測試開始 12004669
ArrayList新增測試開始 6509783
結(jié)果與預(yù)想的有些不太一樣,ArrayList的新增性能并不低。
原因:
可能是經(jīng)過JDK近幾年的更新發(fā)展,對于數(shù)組復(fù)制的實現(xiàn)進行了優(yōu)化,以至于ArrayList的性能也得到了提高。
元素獲取比較
由于LinkedList是鏈表結(jié)構(gòu),沒有角標(biāo)的概念,沒有實現(xiàn)RandomAccess接口,不具備隨機元素訪問功能,所以在get方面表現(xiàn)的差強人意,ArrayList再一次完勝。
public class ListTest {
//迭代次數(shù),集合大?。?
public static int ITERATION_NUM = 100000;
public static void main(String[] agrs) {
try{
getPerformanceCompare();
}catch (Exception e){}
}
//獲取性能比較:
public static void getPerformanceCompare()throws InterruptedException {
Thread.sleep(5000);
//填充ArrayList集合:
List<Integer> arrayList = new ArrayList<Integer>();
for (int x = 0; x < ITERATION_NUM; x++) {
arrayList.add(x);
}
//填充LinkedList集合:
List<Integer> linkedList = new LinkedList<Integer>();
for (int x = 0; x < ITERATION_NUM; x++) {
linkedList.add(x);
}
//創(chuàng)建隨機數(shù)對象:
Random random = new Random();
long start = System.nanoTime();
for (int x = 0; x < ITERATION_NUM; x++) {
int j = random.nextInt(x + 1);
int k = linkedList.get(j);
}
long end = System.nanoTime();
System.out.println("LinkedList獲取測試開始 " + (end - start));
start = System.nanoTime();
for (int x = 0; x < ITERATION_NUM; x++) {
int j = random.nextInt(x + 1);
int k = arrayList.get(j);
}
end = System.nanoTime();
System.out.println("ArrayList獲取測試開始 " + (end - start));
}
}
測試結(jié)果:
第一次:
LinkedList獲取測試開始 8190063123
ArrayList獲取測試開始 8590205
第二次:
LinkedList獲取測試開始 8100623160
ArrayList獲取測試開始 11948919
第三次:
LinkedList獲取測試開始 8237722833
ArrayList獲取測試開始 6333427
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
詳談@Cacheable不起作用的原因:bean未序列化問題
這篇文章主要介紹了@Cacheable不起作用的原因:bean未序列化問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01
簡單介紹Java網(wǎng)絡(luò)編程中的HTTP請求
這篇文章主要介紹了簡單介紹Java網(wǎng)絡(luò)編程中的HTTP請求,需要的朋友可以參考下2015-09-09
SpringBoot內(nèi)部調(diào)用事務(wù)不起作用問題的解決方案
這篇文章主要介紹了SpringBoot事務(wù)不起作用問題的解決方案,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-10-10
Java遠程連接Linux服務(wù)器并執(zhí)行命令及上傳文件功能
這篇文章主要介紹了Java遠程連接Linux服務(wù)器并執(zhí)行命令及上傳文件功能,本文是小編整理的代碼筆記,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2018-05-05
關(guān)于springcloud集成nacos遇到的問題
這篇文章主要介紹了關(guān)于springcloud集成nacos遇到的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01

