1.推薦使用subList處理局部列表
需求:一個(gè)列表100個(gè)元素,現(xiàn)在要?jiǎng)h除索引位置為20-30的元素壁晒,如果使用循環(huán)赁温,代碼如下:
public static void main(String[] arg){
//初始化一個(gè)固定長(zhǎng)度不可變列表
List<Integer> initData = Collections.nCopies(100,0);
//轉(zhuǎn)化為可變列表
List<Integer> list = new ArrayList<Integer>(initData);
//遍歷
for(int i=0;i < list.seze)();i++){
if(i>=20 && i <30){
list.remove(i);
}
}
}
其實(shí)我們可以使用subList來(lái)處理
public static void main(String[] arg){
//初始化一個(gè)固定長(zhǎng)度不可變列表
List<Integer> initData = Collections.nCopies(100,0);
//轉(zhuǎn)化為可變列表
List<Integer> list = new ArrayList<Integer>(initData);
list.subList(20,30).clear();
}
subList返回的是原始列表的一個(gè)試圖挑势,輸出這個(gè)視圖中的所有元素最終會(huì)反映到原始列表
2.生成子列表后不要再操作原列表
public static void main(String[] arg){
List<Integer> srcList = new ArrayList<>();
srcList.add("a");
srcList.add("b");
srcList.add("c");
List<Integer> subList = srcList.subList(0,2);
//操作原列表
srcList.add("D");
System.out.println("原列表長(zhǎng)度:"+srcList.size());
System.out.println("子列表長(zhǎng)度:"+subList.size());
}
運(yùn)行在subList.size()處報(bào)錯(cuò)
- 原列表變化后,subList取出的這子列表不會(huì)生成新的列表申眼,詳細(xì)可查看subList的源碼(原因出現(xiàn)在構(gòu)造參數(shù)的修改計(jì)數(shù)器上)
- 可以通過
list = Collection.unmodiflagList(list)
設(shè)置原列表為只讀狀態(tài)瞒津,避免subList后對(duì)原列表的更改 - 如果subList生成的試圖有多個(gè),那么子列表也不可以修改
3.使用Comparator進(jìn)行排序
在Java中要想給數(shù)據(jù)排序有兩種實(shí)現(xiàn)方式豺型,一種是實(shí)現(xiàn)Comparable接口仲智,一種是實(shí)現(xiàn)Comparator接口,這兩種有什么區(qū)別呢姻氨?
public class Employee implements Comparable<Employee>{
private int id;
private String name;
private Postion position;
public Employee(int _id,String _name,Position _position){
this.id = _id;
this.name= _name;
this.position = _position;
}
//省略getter,setter
//根據(jù)id進(jìn)行排序
@Override
public int compareTo(Employee o){
return new CompareToBuilder().append(id,o.id).toComparison();
}
@Override
public String toString(){
return ToStringBuilder.reflectionToString(this);
}
}
public enum Position(){
Boss,Manager,Staff
}
排序
List<Empoyee> list = new ArrayList<>();
//添加元素省略
//按照id排序
Collection.sort(list);
那么我們?nèi)绻胍凑章毼籶osition進(jìn)行排序钓辆,那該怎么辦?Collection.sort有一個(gè)重載的方法Collection.sort(List<T> list,Comparator<? super T> c),代碼如下:
class PositionComparator implements Comparator<Employee>{
@Override
public int compare(Employee o1,Employee o2){
return o1.getPosition().compareTo(o2.getPosition());
}
}
那么倒序排列是否也要重寫排序器肴焊?不用
- 直接使用Collection.reverse(List<?> list)
- 通過Collection.sort<list,Collections.reverseOrder(new PositionComparator)>
那么如果職位相同再按照id排序該怎么處理:
public int compareTo(Employee o){
return new CompareToBuilder
.append(position,o.position).toComparison()
.append(id,o.id).toComparison();
}
4.不推薦使用binarySearch對(duì)列表進(jìn)行檢索
Collections.binarySearch:使用二分搜索法收縮指定列表以獲取指定對(duì)象前联,其功能與indexOf是相同的。但是使用binarySearch需要注意:
- binarySearch使用前必須對(duì)列表進(jìn)行排序娶眷,這是二分法的首要條件
- 對(duì)列表排序會(huì)打破有規(guī)則的業(yè)務(wù)數(shù)據(jù)似嗤,慎用
- binarySearch在性能上相比indexOf是最好的選擇
5.集合中的元素必須做到compareTo與equals同步
public class city implements Comparable<city>{
private int code;
private String name;
public Employee(int _code,String _name){
this.id = _id;
this.name= _name;
}
//省略getter,setter
//根據(jù)name進(jìn)行排序
@Override
public int compareTo(Employee o){
return new CompareToBuilder().append(name,o.name).toComparison();
}
@Override
public boolean equals(Object obj){
if(onj == null){
return false;
}
if(obj == this){
return true;
}
if(obj.getClass() != getClass()){
return false;
}
City city = (City) obj;
//根據(jù)code判斷是否相等
return new EqualsBuilder().append(code,city.code).isEquals();
}
@Override
public String toString(){
return ToStringBuilder.reflectionToString(this);
}
}
public static void main(String[] arg){
List<Integer> cities = new ArrayList<>();
cities.add(new City("021","上海"));
cities.add(new City("021","滬"));
//排序
Collections.sort(cities);
//查找對(duì)象
City city = new City("021","滬");
List<Integer> subList = srcList.subList(0,2);
//indexOf取得索引值
int index1 = cities.indexOf(city);
//binarySearch取得索引值
int index2 = Collections.binarySearch(cities.city);
System.out.println("indexOf取得索引值:"+ index1);// 0
System.out.println("binarySearch取得索引值index2);// 1
}
為什么結(jié)果不一樣呢?indexOf是使用equals判斷的届宠,binarySearch是通過compareTo方法烁落,而這兩個(gè)方法并不一致乘粒,所以結(jié)果不一樣
6.集合運(yùn)算使用更優(yōu)雅的方式
- 并集:list1.addAll(list2)
- 交集:list1.retainAll(list2)
- 差集:list1.removeAll(list2)
- 無(wú)重復(fù)并集:list2.removeAll(list1);list1.addAll(list2)