欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
Java工程師該如何編寫(xiě)高效代碼?

阿里妹導讀:世界上只有兩種物質(zhì):高效率和低效率;世界上只有兩種人:高效率的人和低效率的人?!挷{

同理,世界上只有兩種代碼:高效代碼和低效代碼;世界上只有兩種人:編寫(xiě)高效代碼的人和編寫(xiě)低效代碼的人。如何編寫(xiě)高效代碼,是每個(gè)研發(fā)團隊都面臨的一個(gè)重大問(wèn)題。
本文作者根據實(shí)際經(jīng)驗,查閱了大量資料,總結了'Java高效代碼50例',讓每一個(gè)Java程序員都能編寫(xiě)出'高效代碼'。

1.常量&變量

1.1.直接賦值常量值,禁止聲明新對象

直接賦值常量值,只是創(chuàng )建了一個(gè)對象引用,而這個(gè)對象引用指向常量值。

反例:


Long i = new Long(1L);String s = new String('abc');

正例:


Long i = 1L;String s = 'abc';


1.2.當成員變量值無(wú)需改變時(shí),盡量定義為靜態(tài)常量

在類(lèi)的每個(gè)對象實(shí)例中,每個(gè)成員變量都有一份副本,而成員靜態(tài)常量只有一份實(shí)例。

反例:




public class HttpConnection { private final long timeout = 5L; ...}

正例:




public class HttpConnection {    private static final long TIMEOUT = 5L;    ...}

1.3.盡量使用基本數據類(lèi)型,避免自動(dòng)裝箱和拆箱

Java 中的基本數據類(lèi)型double、float、long、int、short、char、boolean,分別對應包裝類(lèi)Double、Float、Long、Integer、Short、Character、Boolean。JVM支持基本類(lèi)型與對應包裝類(lèi)的自動(dòng)轉換,被稱(chēng)為自動(dòng)裝箱和拆箱。裝箱和拆箱都是需要CPU和內存資源的,所以應盡量避免使用自動(dòng)裝箱和拆箱。

反例:





Integer sum = 0;int[] values = ...;for (int value : values) { sum = value; // 相當于result = Integer.valueOf(result.intValue() value);}

正例:





int sum = 0;int[] values = ...;for (int value : values) {    sum  = value;}

1.4.如果變量的初值會(huì )被覆蓋,就沒(méi)有必要給變量賦初值

反例:






List<UserDO> userList = new ArrayList<>();if (isAll) { userList = userDAO.queryAll();} else { userList = userDAO.queryActive();}

正例:






List<UserDO> userList;if (isAll) {    userList = userDAO.queryAll();} else {    userList = userDAO.queryActive();}

1.5.盡量使用函數內的基本類(lèi)型臨時(shí)變量

在函數內,基本類(lèi)型的參數和臨時(shí)變量都保存在棧(Stack)中,訪(fǎng)問(wèn)速度較快;對象類(lèi)型的參數和臨時(shí)變量的引用都保存在棧(Stack)中,內容都保存在堆(Heap)中,訪(fǎng)問(wèn)速度較慢。在類(lèi)中,任何類(lèi)型的成員變量都保存在堆(Heap)中,訪(fǎng)問(wèn)速度較慢。

反例:









public final class Accumulator { private double result = 0.0D; public void addAll(@NonNull double[] values) { for(double value : values) { result = value; } } ...}

正例:











public final class Accumulator {    private double result = 0.0D;    public void addAll(@NonNull double[] values) {        double sum = 0.0D;        for(double value : values) {            sum  = value;        }        result  = sum;    }    ...}

1.6.盡量不要在循環(huán)體外定義變量

在老版JDK中,建議“盡量不要在循環(huán)體內定義變量”,但是在新版的JDK中已經(jīng)做了優(yōu)化。通過(guò)對編譯后的字節碼分析,變量定義在循環(huán)體外和循環(huán)體內沒(méi)有本質(zhì)的區別,運行效率基本上是一樣的。

反而,根據“ 局部變量作用域最小化 ”原則,變量定義在循環(huán)體內更科學(xué)更便于維護,避免了延長(cháng)大對象生命周期導致延緩回收問(wèn)題 。

反例:









UserVO userVO;List<UserDO> userDOList = ...;List<UserVO> userVOList = new ArrayList<>(userDOList.size());for (UserDO userDO : userDOList) { userVO = new UserVO(); userVO.setId(userDO.getId()); ... userVOList.add(userVO);}

正例:








List<UserDO> userDOList = ...;List<UserVO> userVOList = new ArrayList<>(userDOList.size());for (UserDO userDO : userDOList) {    UserVO userVO = new UserVO();    userVO.setId(userDO.getId());    ...    userVOList.add(userVO);}

1.7.不可變的靜態(tài)常量,盡量使用非線(xiàn)程安全類(lèi)

不可變的靜態(tài)常量,雖然需要支持多線(xiàn)程訪(fǎng)問(wèn),也可以使用非線(xiàn)程安全類(lèi)。

反例:







public static final Map<String, Class> CLASS_MAP;static { Map<String, Class> classMap = new ConcurrentHashMap<>(16); classMap.put('VARCHAR', java.lang.String.class); ... CLASS_MAP = Collections.unmodifiableMap(classMap);}

正例:







public static final Map<String, Class> CLASS_MAP;static {    Map<String, Class> classMap = new HashMap<>(16);    classMap.put('VARCHAR', java.lang.String.class);    ...    CLASS_MAP = Collections.unmodifiableMap(classMap);}


1.8.不可變的成員變量,盡量使用非線(xiàn)程安全類(lèi)

不可變的成員變量,雖然需要支持多線(xiàn)程訪(fǎng)問(wèn),也可以使用非線(xiàn)程安全類(lèi)。

反例:


















@Servicepublic class StrategyFactory implements InitializingBean { @Autowired private List<Strategy> strategyList; private Map<String, Strategy> strategyMap; @Override public void afterPropertiesSet() { if (CollectionUtils.isNotEmpty(strategyList)) { int size = (int) Math.ceil(strategyList.size() * 4.0 / 3); Map<String, Strategy> map = new ConcurrentHashMap<>(size); for (Strategy strategy : strategyList) { map.put(strategy.getType(), strategy); } strategyMap = Collections.unmodifiableMap(map); } } ...}

正例:

















@Servicepublic class StrategyFactory implements InitializingBean {    @Autowired    private List<Strategy> strategyList;    private Map<String, Strategy> strategyMap;    @Override    public void afterPropertiesSet() {        if (CollectionUtils.isNotEmpty(strategyList)) {            int size = (int) Math.ceil(strategyList.size() * 4.0 / 3);            Map<String, Strategy> map = new HashMap<>(size);            for (Strategy strategy : strategyList) {                map.put(strategy.getType(), strategy);            }            strategyMap = Collections.unmodifiableMap(map);        }    }    ...


2.對象&類(lèi)

2.1.禁止使用JSON轉化對象

JSON提供把對象轉化為JSON字符串、把JSON字符串轉為對象的功能,于是被某些人用來(lái)轉化對象。這種對象轉化方式,雖然在功能上沒(méi)有問(wèn)題,但是在性能上卻存在問(wèn)題。

反例:


List<UserDO> userDOList = ...;List<UserVO> userVOList = JSON.parseArray(JSON.toJSONString(userDOList), UserVO.class);
正例:








List<UserDO> userDOList = ...;List<UserVO> userVOList = new ArrayList<>(userDOList.size());for (UserDO userDO : userDOList) {    UserVO userVO = new UserVO();    userVO.setId(userDO.getId());    ...    userVOList.add(userVO);}

2.2.盡量不使用反射賦值對象

用反射賦值對象,主要優(yōu)點(diǎn)是節省了代碼量,主要缺點(diǎn)卻是性能有所下降。

反例:







List<UserDO> userDOList = ...;List<UserVO> userVOList = new ArrayList<>(userDOList.size());for (UserDO userDO : userDOList) { UserVO userVO = new UserVO(); BeanUtils.copyProperties(userDO, userVO); userVOList.add(userVO);}

正例:








List<UserDO> userDOList = ...;List<UserVO> userVOList = new ArrayList<>(userDOList.size());for (UserDO userDO : userDOList) {    UserVO userVO = new UserVO();    userVO.setId(userDO.getId());    ...    userVOList.add(userVO);}


2.3.采用Lambda表達式替換內部匿名類(lèi)

對于大多數剛接觸JDK8的同學(xué)來(lái)說(shuō),都會(huì )認為L(cháng)ambda表達式就是匿名內部類(lèi)的語(yǔ)法糖。實(shí)際上, Lambda表達式在大多數虛擬機中采用invokeDynamic指令實(shí)現,相對于匿名內部類(lèi)在效率上會(huì )更高一些。

反例:










List<User> userList = ...;Collections.sort(userList, new Comparator<User>() { @Override public int compare(User user1, User user2) { Long userId1 = user1.getId(); Long userId2 = user2.getId(); ... return userId1.compareTo(userId2); }});

正例:







List<User> userList = ...;Collections.sort(userList, (user1, user2) -> {    Long userId1 = user1.getId();    Long userId2 = user2.getId();    ...    return userId1.compareTo(userId2);});


2.4.盡量避免定義不必要的子類(lèi)

多一個(gè)類(lèi)就需要多一份類(lèi)加載,所以盡量避免定義不必要的子類(lèi)。

反例:







public static final Map<String, Class> CLASS_MAP = Collections.unmodifiableMap(new HashMap<String, Class>(16) { private static final long serialVersionUID = 1L; { put('VARCHAR', java.lang.String.class); }});

正例:







public static final Map<String, Class> CLASS_MAP;static {    Map<String, Class> classMap = new HashMap<>(16);    classMap.put('VARCHAR', java.lang.String.class);    ...    CLASS_MAP = Collections.unmodifiableMap(classMap);}


2.5.盡量指定類(lèi)的final修飾符

為類(lèi)指定final修飾符,可以讓該類(lèi)不可以被繼承。如果指定了一個(gè)類(lèi)為final,則該類(lèi)所有的方法都是final的,Java編譯器會(huì )尋找機會(huì )內聯(lián)所有的final方法。內聯(lián)對于提升Java運行效率作用重大,具體可參見(jiàn)Java運行期優(yōu)化,能夠使性能平均提高50%。

反例:



public class DateHelper { ...}

正例:



public final class DateHelper {    ...}

注意:使用Spring的AOP特性時(shí),需要對Bean進(jìn)行動(dòng)態(tài)代理,如果Bean類(lèi)添加了final修飾,會(huì )導致異常。

3.方法

3.1.把跟類(lèi)成員變量無(wú)關(guān)的方法聲明成靜態(tài)方法

靜態(tài)方法的好處就是不用生成類(lèi)的實(shí)例就可以直接調用。靜態(tài)方法不再屬于某個(gè)對象,而是屬于它所在的類(lèi)。只需要通過(guò)其類(lèi)名就可以訪(fǎng)問(wèn),不需要再消耗資源去反復創(chuàng )建對象。即便在類(lèi)內部的私有方法,如果沒(méi)有使用到類(lèi)成員變量,也應該聲明為靜態(tài)方法。

反例:





public int getMonth(Date date) { Calendar calendar = Calendar.getInstance(); calendar.setTime(date); return calendar.get(Calendar.MONTH) 1;}

正例:





public static int getMonth(Date date) {  Calendar calendar = Calendar.getInstance();  calendar.setTime(date);  return calendar.get(Calendar.MONTH)   1;}

3.2.盡量使用基本數據類(lèi)型作為方法參數類(lèi)型,避免不必要的裝箱、拆箱和空指針判斷


反例:






public static double sum(Double value1, Double value2) { double double1 = Objects.isNull(value1) ? 0.0D : value1; double double2 = Objects.isNull(value2) ? 0.0D : value2; return double1 double2;}double result = sum(1.0D, 2.0D);

正例:




public static double sum(double value1, double value2) {    return value1   value2;}double result = sum(1.0D, 2.0D);


3.3.盡量使用基本數據類(lèi)型作為方法返回值類(lèi)型,避免不必要的裝箱、拆箱和空指針判斷

在JDK類(lèi)庫的方法中,很多方法返回值都采用了基本數據類(lèi)型,首先是為了避免不必要的裝箱和拆箱,其次是為了避免返回值的空指針判斷。比如:Collection.isEmpty()和Map.size()。

反例:













public static Boolean isValid(UserDO user) { if (Objects.isNull(user)) { return false; } return Boolean.TRUE.equals(user.getIsValid());}
// 調用代碼UserDO user = ...;Boolean isValid = isValid(user);if (Objects.nonNull(isValid) && isValid.booleanValue()) { ...}

正例:












public static boolean isValid(UserDO user) {    if (Objects.isNull(user)) {        return false;    }  return Boolean.TRUE.equals(user.getIsValid());}
// 調用代碼UserDO user = ...;if (isValid(user)) { ...}


3.4.協(xié)議方法參數值非空,避免不必要的空指針判斷

協(xié)議編程,可以@NonNull和@Nullable標注參數,是否遵循全憑調用者自覺(jué)。

反例:






public static boolean isValid(UserDO user) { if (Objects.isNull(user)) { return false; } return Boolean.TRUE.equals(user.getIsValid());}

正例:



public static boolean isValid(@NonNull UserDO user) {  return Boolean.TRUE.equals(user.getIsValid());}


3.5.協(xié)議方法返回值非空,避免不必要的空指針判斷

協(xié)議編程,可以@NonNull和@Nullable標注參數,是否遵循全憑實(shí)現者自覺(jué)。

反例:












// 定義接口public interface OrderService { public List<OrderVO> queryUserOrder(Long userId);}
// 調用代碼List<OrderVO> orderList = orderService.queryUserOrder(userId);if (CollectionUtils.isNotEmpty(orderList)) { for (OrderVO order : orderList) { ... }}

正例:











// 定義接口public interface OrderService {    @NonNull    public List<OrderVO> queryUserOrder(Long userId);}
// 調用代碼List<OrderVO> orderList = orderService.queryUserOrder(userId);for (OrderVO order : orderList) { ...}


3.6.被調用方法已支持判空處理,調用方法無(wú)需再進(jìn)行判空處理

反例:




UserDO user = null;if (StringUtils.isNotBlank(value)) { user = JSON.parseObject(value, UserDO.class);}

正例:

UserDO user = JSON.parseObject(value, UserDO.class);


3.7.盡量避免不必要的函數封裝

方法調用會(huì )引起入棧和出棧,導致消耗更多的CPU和內存,應當盡量避免不必要的函數封裝。當然,為了使代碼更簡(jiǎn)潔、更清晰、更易維護,增加一定的方法調用所帶來(lái)的性能損耗是值得的。

反例:







// 函數封裝public static boolean isVip(Boolean isVip) { return Boolean.TRUE.equals(isVip);}
// 使用代碼boolean isVip = isVip(user.getVip());

正例:

boolean isVip = Boolean.TRUE.equals(user.getVip());

3.8.盡量指定方法的final修飾符

方法指定final修飾符,可以讓方法不可以被重寫(xiě),Java編譯器會(huì )尋找機會(huì )內聯(lián)所有的final方法。內聯(lián)對于提升Java運行效率作用重大,具體可參見(jiàn)Java運行期優(yōu)化,能夠使性能平均提高50%。

注意:所有的private方法會(huì )隱式地被指定final修飾符,所以無(wú)須再為其指定final修飾符。

反例:






public class Rectangle { ... public double area() { ... }}

正例:






public class Rectangle {    ...    public final double area() {        ...    }}

注意:使用Spring的AOP特性時(shí),需要對Bean進(jìn)行動(dòng)態(tài)代理,如果方法添加了final修飾,將不會(huì )被代理。

4.表達式

4.1.盡量減少方法的重復調用

反例:




List<UserDO> userList = ...;for (int i = 0; i < userList.size(); i ) { ...}

正例:





List<UserDO> userList = ...;int userLength = userList.size();for (int i = 0; i < userLength; i  ) {    ...}


4.2.盡量避免不必要的方法調用

反例:




List<UserDO> userList = userDAO.queryActive();if (isAll) { userList = userDAO.queryAll();}

正例:






List<UserDO> userList;if (isAll) {    userList = userDAO.queryAll();} else {    userList = userDAO.queryActive();}


4.3.盡量使用移位來(lái)代替正整數乘除

用移位操作可以極大地提高性能。對于乘除2^n(n為正整數)的正整數計算,可以用移位操作來(lái)代替。

反例:


int num1 = a * 4;int num2 = a / 4;

正例:


int num1 = a << 2;int num2 = a >> 2;


4.4.提取公共表達式,避免重復計算

提取公共表達式,只計算一次值,然后重復利用值。

反例:

double distance = Math.sqrt((x2 - x1) * (x2 - x1) (y2 - y1) * (y2 - y1));
正例:





double dx = x2 - x1;double dy = y2 - y1;double distance = Math.sqrt(dx * dx   dy * dy);double distance = Math.sqrt(Math.pow(x2 - x1, 2)   Math.pow(y2 - y1, 2));


4.5.盡量不在條件表達式中用!取反

使用!取反會(huì )多一次計算,如果沒(méi)有必要則優(yōu)化掉。

反例:





if (!(a >= 10)) { ... // 條件處理1} else { ... // 條件處理2}

正例:





if (a < 10) {    ... // 條件處理1} else {    ... // 條件處理2}


4.6.對于多常量選擇分支,盡量使用switch語(yǔ)句而不是if-else語(yǔ)句

if-else語(yǔ)句,每個(gè)if條件語(yǔ)句都要加裝計算,直到if條件語(yǔ)句為true為止。switch語(yǔ)句進(jìn)行了跳轉優(yōu)化,Java中采用tableswitch或lookupswitch指令實(shí)現,對于多常量選擇分支處理效率更高。經(jīng)過(guò)試驗證明:在每個(gè)分支出現概率相同的情況下,低于5個(gè)分支時(shí)if-else語(yǔ)句效率更高,高于5個(gè)分支時(shí)switch語(yǔ)句效率更高。

反例:









if (i == 1) { ...; // 分支1} else if (i == 2) { ...; // 分支2} else if (i == ...) { ...; // 分支n} else { ...; // 分支n 1}

正例:














switch (i) {    case 1 :        ... // 分支1        break;    case 2 :        ... // 分支2        break;    case ... :        ... // 分支n        break;    default :        ... // 分支n 1        break;}

備注:如果業(yè)務(wù)復雜,可以采用Map實(shí)現策略模式。

5.字符串

5.1.盡量不要使用正則表達式匹配

正則表達式匹配效率較低,盡量使用字符串匹配操作。

反例:



String source = 'a::1,b::2,c::3,d::4';String target = source.replaceAll('::', '=');Stringp[] targets = source.spit('::');

正例:



String source = 'a::1,b::2,c::3,d::4';String target = source.replace('::', '=');Stringp[] targets = StringUtils.split(source, '::');


5.2.盡量使用字符替換字符串

字符串的長(cháng)度不確定,而字符的長(cháng)度固定為1,查找和匹配的效率自然提高了。

反例:



String source = 'a:1,b:2,c:3,d:4';int index = source.indexOf(':');String target = source.replace(':', '=');

正例:



String source = 'a:1,b:2,c:3,d:4';int index = source.indexOf(':');String target = source.replace(':', '=');


5.3.盡量使用StringBuilder進(jìn)行字符串拼接

String是final類(lèi),內容不可修改,所以每次字符串拼接都會(huì )生成一個(gè)新對象。StringBuilder在初始化時(shí)申請了一塊內存,以后的字符串拼接都在這塊內存中執行,不會(huì )申請新內存和生成新對象。

反例:







String s = '';for (int i = 0; i < 10; i ) { if (i != 0) { s = ','; } s = i;}

例:







StringBuilder sb = new StringBuilder(128);for (int i = 0; i < 10; i  ) {    if (i != 0) {        sb.append(',');    }    sb.append(i);}


5.4.不要使用'' 轉化字符串

使用'' 進(jìn)行字符串轉化,使用方便但是效率低,建議使用String.valueOf.

反例:


int i = 12345;String s = '' i;

正例:


int i = 12345;String s = String.valueOf(i);


6.數組

6.1.不要使用循環(huán)拷貝數組,盡量使用System.arraycopy拷貝數組

推薦使用System.arraycopy拷貝數組,也可以使用Arrays.copyOf拷貝數組。

反例:





int[] sources = new int[] {1, 2, 3, 4, 5};int[] targets = new int[sources.length];for (int i = 0; i < targets.length; i ) { targets[i] = sources[i];}

正例:



int[] sources = new int[] {1, 2, 3, 4, 5};int[] targets = new int[sources.length];System.arraycopy(sources, 0, targets, 0, targets.length);


6.2.集合轉化為類(lèi)型T數組時(shí),盡量傳入空數組T[0]

將集合轉換為數組有2種形式:toArray(new T[n])和toArray(new T[0])。在舊的Java版本中,建議使用toArray(new T[n]),因為創(chuàng )建數組時(shí)所需的反射調用非常慢。在OpenJDK6后,反射調用是內在的,使得性能得以提高,toArray(new T[0])比toArray(new T[n])效率更高。此外,toArray(new T[n])比toArray(new T[0])多獲取一次列表大小,如果計算列表大小耗時(shí)過(guò)長(cháng),也會(huì )導致toArray(new T[n])效率降低。

反例:


List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5, ...);Integer[] integers = integerList.toArray(new Integer[integerList.size()]);
正例:


List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5, ...);Integer[] integers = integerList.toArray(new Integer[0]); // 勿用new Integer[]{}

建議:集合應該提供一個(gè)toArray(Class<T> clazz)方法,避免無(wú)用的空數組初始化(new T[0])。

6.3.集合轉化為Object數組時(shí),盡量使用toArray()方法

轉化Object數組時(shí),沒(méi)有必要使用toArray[new Object[0]],可以直接使用toArray()。避免了類(lèi)型的判斷,也避免了空數組的申請,所以效率會(huì )更高。

反例:


List<Object> objectList = Arrays.asList(1, '2', 3, '4', 5, ...);Object[] objects = objectList.toArray(new Object[0]);

正例:


List<Object> objectList = Arrays.asList(1, '2', 3, '4', 5, ...);Object[] objects = objectList.toArray();


7.集合

7.1.初始化集合時(shí),盡量指定集合大小

Java集合初始化時(shí)都會(huì )指定一個(gè)默認大小,當默認大小不再滿(mǎn)足數據需求時(shí)就會(huì )擴容,每次擴容的時(shí)間復雜度有可能是O(n)。所以,盡量指定預知的集合大小,就能避免或減少集合的擴容次數。

反例:









List<UserDO> userDOList = ...;Set<Long> userSet = new HashSet<>();Map<Long, UserDO> userMap = new HashMap<>();List<UserVO> userList = new ArrayList<>();for (UserDO userDO : userDOList) { userSet.add(userDO.getId()); userMap.put(userDO.getId(), userDO); userList.add(transUser(userDO));}

正例:










List<UserDO> userDOList = ...;int userSize = userDOList.size();Set<Long> userSet = new HashSet<>(userSize);Map<Long, UserDO> userMap = new HashMap<>((int) Math.ceil(userSize * 4.0 / 3));List<UserVO> userList = new ArrayList<>(userSize);for (UserDO userDO : userDOList) {    userSet.add(userDO.getId());    userMap.put(userDO.getId(), userDO);    userList.add(transUser(userDO));}


7.2.不要使用循環(huán)拷貝集合,盡量使用JDK提供的方法拷貝集合

JDK提供的方法可以一步指定集合的容量,避免多次擴容浪費時(shí)間和空間。同時(shí),這些方法的底層也是調用System.arraycopy方法實(shí)現,進(jìn)行數據的批量拷貝效率更高。

反例:









List<UserDO> user1List = ...;List<UserDO> user2List = ...;List<UserDO> userList = new ArrayList<>(user1List.size() user2List.size());for (UserDO user1 : user1List) { userList.add(user1);}for (UserDO user2 : user2List) { userList.add(user2);}

正例:





List<UserDO> user1List = ...;List<UserDO> user2List = ...;List<UserDO> userList = new ArrayList<>(user1List.size()   user2List.size());userList.addAll(user1List);userList.addAll(user2List);


7.3.盡量使用Arrays.asList轉化數組為列表

原理與'不要使用循環(huán)拷貝集合,盡量使用JDK提供的方法拷貝集合'類(lèi)似。

反例:










List<String> typeList = new ArrayList<>(8);typeList.add('Short');typeList.add('Integer');typeList.add('Long');
String[] names = ...;List<String> nameList = ...;for (String name : names) { nameList.add(name);}

正例:





List<String> typeList = Arrays.asList('Short', 'Integer', 'Long');
String[] names = ...;List<String> nameList = ...;nameList.addAll(Arrays.asList(names));


7.4.直接迭代需要使用的集合

直接迭代需要使用的集合,無(wú)需通過(guò)其它操作獲取數據。

反例:





Map<Long, UserDO> userMap = ...;for (Long userId : userMap.keySet()) { UserDO user = userMap.get(userId); ...}

正例:






Map<Long, UserDO> userMap = ...;for (Map.Entry<Long, UserDO> userEntry : userMap.entrySet()) {    Long userId = userEntry.getKey();    UserDO user = userEntry.getValue();    ...}


7.5.不要使用size方法檢測空,必須使用isEmpty方法檢測空

使用size方法來(lái)檢測空邏輯上沒(méi)有問(wèn)題,但使用isEmpty方法使得代碼更易讀,并且可以獲得更好的性能。任何isEmpty方法實(shí)現的時(shí)間復雜度都是O(1),但是某些size方法實(shí)現的時(shí)間復雜度有可能是O(n)。

反例:








List<UserDO> userList = ...;if (userList.size() == 0) { ...}Map<Long, UserDO> userMap = ...;if (userMap.size() == 0) { ...}

正例:








List<UserDO> userList = ...;if (userList.isEmpty()) {    ...}Map<Long, UserDO> userMap = ...;if (userMap.isEmpty()) {    ...}


7.6.非隨機訪(fǎng)問(wèn)的List,盡量使用迭代代替隨機訪(fǎng)問(wèn)

對于列表,可分為隨機訪(fǎng)問(wèn)和非隨機訪(fǎng)問(wèn)兩類(lèi),可以用是否實(shí)現RandomAccess接口判斷。隨機訪(fǎng)問(wèn)列表,直接通過(guò)get獲取數據不影響效率。而非隨機訪(fǎng)問(wèn)列表,通過(guò)get獲取數據效率極低。

反例:






LinkedList<UserDO> userDOList = ...;int size = userDOList.size();for (int i = 0; i < size; i ) { UserDO userDO = userDOList.get(i); ...}

正例:




LinkedList<UserDO> userDOList = ...;for (UserDO userDO : userDOList) {    ...}

其實(shí),不管列表支不支持隨機訪(fǎng)問(wèn),都應該使用迭代進(jìn)行遍歷。

7.7.盡量使用HashSet判斷值存在

在Java集合類(lèi)庫中,List的contains方法普遍時(shí)間復雜度是O(n),而HashSet的時(shí)間復雜度為O(1)。如果需要頻繁調用contains方法查找數據,可以先將List轉換成HashSet。

反例:








List<Long> adminIdList = ...;List<UserDO> userDOList = ...;List<UserVO> userVOList = new ArrayList<>(userDOList.size());for (UserDO userDO : userDOList) { if (adminIdList.contains(userDO.getId())) { userVOList.add(transUser(userDO)); }}

正例:








Set<Long> adminIdSet = ...;List<UserDO> userDOList = ...;List<UserVO> userVOList = new ArrayList<>(userDOList.size());for (UserDO userDO : userDOList) {    if (adminIdSet.contains(userDO.getId())) {        userVOList.add(transUser(userDO));    }}


7.8.避免先判斷存在再進(jìn)行獲取

如果需要先判斷存在再進(jìn)行獲取,可以直接獲取并判斷空,從而避免了二次查找操作。

反例:









public static UserVO transUser(UserDO user, Map<Long, RoleDO> roleMap) { UserVO userVO = new UserVO(); userVO.setId(user.getId()); ... if (roleMap.contains(user.getRoleId())) { RoleDO role = roleMap.get(user.getRoleId()); userVO.setRole(transRole(role)); }}

正例:









public static UserVO transUser(UserDO user, Map<Long, RoleDO> roleMap) {    UserVO userVO = new UserVO();    userVO.setId(user.getId());    ...    RoleDO role = roleMap.get(user.getRoleId());    if (Objects.nonNull(role)) {        userVO.setRole(transRole(role));    }}


8.異常

8.1.直接捕獲對應的異常

直接捕獲對應的異常,避免用instanceof判斷,效率更高代碼更簡(jiǎn)潔。

反例:









try { saveData();} catch (Exception e) { if (e instanceof IOException) { log.error('保存數據IO異常', e); } else { log.error('保存數據其它異常', e); }}

正例:







try {    saveData();} catch (IOException e) {    log.error('保存數據IO異常', e);} catch (Exception e) {    log.error('保存數據其它異常', e);}


8.2.盡量避免在循環(huán)中捕獲異常

當循環(huán)體拋出異常后,無(wú)需循環(huán)繼續執行時(shí),沒(méi)有必要在循環(huán)體中捕獲異常。因為,過(guò)多的捕獲異常會(huì )降低程序執行效率。

反例:











public Double sum(List<String> valueList) { double sum = 0.0D; for (String value : valueList) { try { sum = Double.parseDouble(value); } catch (NumberFormatException e) { return null; } } return sum;}

正例:











public Double sum(List<String> valueList) {    double sum = 0.0D;    try {        for (String value : valueList) {            sum  = Double.parseDouble(value);        }    } catch (NumberFormatException e) {        return null;    }    return sum;}


8.3.禁止使用異??刂茦I(yè)務(wù)流程

相對于條件表達式,異常的處理效率更低。

反例:







public static boolean isValid(UserDO user) { try { return Boolean.TRUE.equals(user.getIsValid()); } catch(NullPointerException e) { return false; }}

正例:






public static boolean isValid(UserDO user) {    if (Objects.isNull(user)) {        return false;    }  return Boolean.TRUE.equals(user.getIsValid());}


9.緩沖區

9.1.初始化時(shí)盡量指定緩沖區大小

初始化時(shí),指定緩沖區的預期容量大小,避免多次擴容浪費時(shí)間和空間。

反例:


StringBuffer buffer = new StringBuffer();StringBuilder builder = new StringBuilder();

正例:


StringBuffer buffer = new StringBuffer(1024);StringBuilder builder = new StringBuilder(1024);


9.2.盡量重復使用同一緩沖區

針對緩沖區,Java虛擬機需要花時(shí)間生成對象,還要花時(shí)間進(jìn)行垃圾回收處理。所以,盡量重復利用緩沖區。

反例:







StringBuilder builder1 = new StringBuilder(128);builder1.append('update t_user set name = '').append(userName).append('' where id = ').append(userId);statement.executeUpdate(builder1.toString());StringBuilder builder2 = new StringBuilder(128);builder2.append('select id, name from t_user where id = ').append(userId);ResultSet resultSet = statement.executeQuery(builder2.toString());...

正例:







StringBuilder builder = new StringBuilder(128);builder.append('update t_user set name = '').append(userName).append('' where id = ').append(userId);statement.executeUpdate(builder.toString());builder.setLength(0);builder.append('select id, name from t_user where id = ').append(userId);ResultSet resultSet = statement.executeQuery(builder.toString());...

其中,使用setLength方法讓緩沖區重新從0開(kāi)始。

9.3.盡量設計使用同一緩沖區

為了提高程序運行效率,在設計上盡量使用同一緩沖區。

反例:























// 轉化XML(UserDO)public static String toXml(UserDO user) { StringBuilder builder = new StringBuilder(128); builder.append('<UserDO>'); builder.append(toXml(user.getId())); builder.append(toXml(user.getName())); builder.append(toXml(user.getRole())); builder.append('</UserDO>'); return builder.toString();}// 轉化XML(Long)public static String toXml(Long value) { StringBuilder builder = new StringBuilder(128); builder.append('<Long>'); builder.append(value); builder.append('</Long>'); return builder.toString();}...
// 使用代碼UserDO user = ...;String xml = toXml(user);

正例:





















// 轉化XML(UserDO)public static void toXml(StringBuilder builder, UserDO user) {    builder.append('<UserDO>');    toXml(builder, user.getId());    toXml(builder, user.getName());    toXml(builder, user.getRole());    builder.append('</UserDO>');}// 轉化XML(Long)public static void toXml(StringBuilder builder, Long value) {    builder.append('<Long>');    builder.append(value);    builder.append('</Long>');}...
// 使用代碼UserDO user = ...;StringBuilder builder = new StringBuilder(1024);toXml(builder, user);String xml = builder.toString();

去掉每個(gè)轉化方法中的緩沖區申請,申請一個(gè)緩沖區給每個(gè)轉化方法使用。從時(shí)間上來(lái)說(shuō),節約了大量緩沖區的申請釋放時(shí)間;從空間上來(lái)說(shuō),節約了大量緩沖區的臨時(shí)存儲空間。

9.4.盡量使用緩沖流減少I(mǎi)O操作

使用緩沖流BufferedReader、BufferedWriter、BufferedInputStream、BufferedOutputStream等,可以大幅較少I(mǎi)O次數并提升IO速度。

反例:










try (FileInputStream input = new FileInputStream('a'); FileOutputStream output = new FileOutputStream('b')) { int size = 0; byte[] temp = new byte[1024]; while ((size = input.read(temp)) != -1) { output.write(temp, 0, size); }} catch (IOException e) { log.error('復制文件異常', e);}

正例:










try (BufferedInputStream input = new BufferedInputStream(new FileInputStream('a'));    BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream('b'))) {    int size = 0;    byte[] temp = new byte[1024];    while ((size = input.read(temp)) != -1) {        output.write(temp, 0, size);    }} catch (IOException e) {    log.error('復制文件異常', e);}
其中,可以根據實(shí)際情況手動(dòng)指定緩沖流的大小,把緩沖流的緩沖作用發(fā)揮到最大。

10.線(xiàn)程

10.1.在單線(xiàn)程中,盡量使用非線(xiàn)程安全類(lèi)

使用非線(xiàn)程安全類(lèi),避免了不必要的同步開(kāi)銷(xiāo)。

反例:


StringBuffer buffer = new StringBuffer(128);buffer.append('select * from ').append(T_USER).append(' where id = ?');

正例:


StringBuilder buffer = new StringBuilder(128);buffer.append('select * from ').append(T_USER).append(' where id = ?');


10.2.在多線(xiàn)程中,盡量使用線(xiàn)程安全類(lèi)

使用線(xiàn)程安全類(lèi),比自己實(shí)現的同步代碼更簡(jiǎn)潔更高效。

反例:







private volatile int counter = 0;public void access(Long userId) { synchronized (this) { counter ; } ...}

正例:





private final AtomicInteger counter = new AtomicInteger(0);public void access(Long userId) {    counter.incrementAndGet();    ...}


10.3.盡量減少同步代碼塊范圍

在一個(gè)方法中,可能只有一小部分的邏輯是需要同步控制的,如果同步控制了整個(gè)方法會(huì )影響執行效率。所以,盡量減少同步代碼塊的范圍,只對需要進(jìn)行同步的代碼進(jìn)行同步。

反例:





private volatile int counter = 0;public synchronized void access(Long userId) { counter ; ... // 非同步操作}

正例:







private volatile int counter = 0;public void access(Long userId) {    synchronized (this) {        counter  ;    }    ... // 非同步操作}


10.4.盡量合并為同一同步代碼塊

同步代碼塊是有性能開(kāi)銷(xiāo)的,如果確定可以合并為同一同步代碼塊,就應該盡量合并為同一同步代碼塊。

反例:











// 處理單一訂單public synchronized handleOrder(OrderDO order) { ...}
// 處理所有訂單public void handleOrder(List<OrderDO> orderList) { for (OrderDO order : orderList) { handleOrder(order); }}

正例:











// 處理單一訂單public handleOrder(OrderDO order) {    ...}
// 處理所有訂單public synchronized void handleOrder(List<OrderDO> orderList) { for (OrderDO order : orderList) { handleOrder(order); }}


10.5.盡量使用線(xiàn)程池減少線(xiàn)程開(kāi)銷(xiāo)

多線(xiàn)程中兩個(gè)必要的開(kāi)銷(xiāo):線(xiàn)程的創(chuàng )建和上下文切換。采用線(xiàn)程池,可以盡量地避免這些開(kāi)銷(xiāo)。

反例:



public void executeTask(Runnable runnable) { new Thread(runnable).start();}

正例:




private static final ExecutorService EXECUTOR_SERVICE = Executors.newFixedThreadPool(10);public void executeTask(Runnable runnable) {    executorService.execute(runnable);}


后記

作為一名長(cháng)期奮戰在業(yè)務(wù)一線(xiàn)的'IT民工',沒(méi)有機會(huì )去研究什么高深莫測的'理論',只能專(zhuān)注于眼前看得見(jiàn)摸得著(zhù)的'技術(shù)',致力于做到'干一行、愛(ài)一行、專(zhuān)一行、精一行'。
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Java 代碼精簡(jiǎn)之道
Java單元測試技巧之JSON序列化
工作四年,分享50個(gè)讓你代碼更好的小建議
Java函數優(yōu)雅之道(下)
DO、DTO和VO分層設計的好處
如何把愛(ài)和規矩同時(shí)給孩子?
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久