溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

Java中不常用的開(kāi)發(fā)技巧有哪些

發(fā)布時(shí)間:2023-04-27 10:25:34 來(lái)源:億速云 閱讀:109 作者:iii 欄目:開(kāi)發(fā)技術(shù)

本文小編為大家詳細(xì)介紹“Java中不常用的開(kāi)發(fā)技巧有哪些”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“Java中不常用的開(kāi)發(fā)技巧有哪些”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來(lái)學(xué)習(xí)新知識(shí)吧。

BigDecimal

我們先來(lái)看一段代碼:

BigDecimal b1= new BigDecimal(0.1);
System.out.println(b1);

大家可以猜一下這個(gè)執(zhí)行的結(jié)果會(huì)是什么內(nèi)容呢?

結(jié)果是 0.1 么?如果不是 0.1 的話(huà),那么執(zhí)行輸出的話(huà),會(huì)出現(xiàn)什么內(nèi)容,如果你知道,那么恭喜你,如果你不知道的話(huà),那么就得認(rèn)真學(xué)習(xí)一下拉。

結(jié)果顯而易見(jiàn),肯定不是 0.1 。

我們看看他的執(zhí)行結(jié)果是什么內(nèi)容,然后再來(lái)說(shuō),應(yīng)該使用什么方式。

0.1000000000000000055511151231257827021181583404541015625

當(dāng)看到這個(gè)內(nèi)容的,很多人恍然大悟,一眼就看出來(lái),精度丟失了,所以導(dǎo)致了這種情況的發(fā)生,成這種問(wèn)題的原因是 0.1 這個(gè)數(shù)字計(jì)算機(jī)是無(wú)法精確表示的,送給 BigDecimal 的時(shí)候就已經(jīng)丟精度了.double類(lèi)型 那么我們應(yīng)該怎么去處理這個(gè) double 類(lèi)型的參數(shù)呢?

其實(shí)很簡(jiǎn)單,方式有兩種,第一種:

BigDecimal bigDecimal = new BigDecimal("0.1");
System.out.println(bigDecimal);

第二種:

BigDecimal bigDecimal1 = BigDecimal.valueOf(0.1);
System.out.println(bigDecimal1);

實(shí)際上,在本質(zhì)上,這兩個(gè)方法并沒(méi)有區(qū)別,因?yàn)椤?code>valueOf 在實(shí)現(xiàn)上,就是轉(zhuǎn)成了一個(gè)字符串。

BigDecimal 當(dāng)中的 valueOf 中是把浮點(diǎn)數(shù)轉(zhuǎn)換成了字符串來(lái)構(gòu)造的 BigDecimal,因此避免了問(wèn)題。

源碼如下:

Java中不常用的開(kāi)發(fā)技巧有哪些

compareTo

這個(gè)方法我們經(jīng)常用到,用來(lái)比較 BigDecimal 的,在 BigDecimal 中使用 equals 可能會(huì)導(dǎo)致結(jié)果錯(cuò)誤,BigDecimal 中提供了 compareTo 方法,在很多時(shí)候需要使用 compareTo 比較兩個(gè)值。如下所示:

        BigDecimal b1 = new BigDecimal("10.0");
        BigDecimal b2 = new BigDecimal("10.00");
        System.out.println(b1.equals(b2));
        System.out.println(b1.compareTo(b2));

我們肯定遇到過(guò)這種,用 compareTo 比較的時(shí)候,自己臆想的和代碼執(zhí)行的,肯定不一樣,于是就有了自己實(shí)驗(yàn)的過(guò)程。

出現(xiàn)此種結(jié)果的原因是,equals不僅比較了值是否相等,還比較了精度是否相同。示例中,由于兩個(gè)值的精度不同,所有結(jié)果也就不相同。而 compareTo 是只比較值的大小。返回的值為-1(小于),0(等于),1(大于)。

List

說(shuō)到 List 絕對(duì)不陌生,甚至天天在用,List 轉(zhuǎn)數(shù)組,應(yīng)該怎么操作呢?

其實(shí)很簡(jiǎn)單,就是 toArray。

toArray

List<String> list = new ArrayList<>();

String[] strings = list.toArray(new String[list.size()]);

兩個(gè)方法,不帶參數(shù)的 toArray 就是直接調(diào)用 Arrays.copyOf(elementData, size),將 List 中的元素對(duì)象的引用裝在一個(gè)新的生成數(shù)組中。

帶參數(shù)的則是會(huì)返回指定類(lèi)型(必須為 List 元素類(lèi)型的父類(lèi)或本身)的數(shù)組對(duì)象,如果 a.length 小于 List 元素個(gè)數(shù)就直接調(diào)用 Arrays 的 copyOf() 方法進(jìn)行拷貝并且返回新數(shù)組對(duì)象,新數(shù)組中也是裝的 List 元素對(duì)象的引用,否則先調(diào)用System.arraycopy()將 List 元素對(duì)象的引用裝在a數(shù)組中,如果a數(shù)組還有剩余的空間,則在 a[size] 放置一個(gè) nullsize 就是 list 中元素的個(gè)數(shù),這個(gè) null 值可以使得 toArray(T[] a) 方法調(diào)用者可以判斷 null 后面已經(jīng)沒(méi)有 list 元素了.

其實(shí)在業(yè)務(wù)中,我們更多的都是直接使用第二個(gè),第一個(gè)五參數(shù)的方法,很多時(shí)候都是作為測(cè)試來(lái)存在的。

JDK8的小玩意

其實(shí)了不起更想說(shuō)的,還是 JDK8 中的一些肖操作,他會(huì)精簡(jiǎn)我們的代碼,而且,邏輯也更加的清晰,為什么這么說(shuō),因?yàn)楝F(xiàn)在百分之八九十的公司都還是在使用 JDK8 ,升級(jí)版本的,還并不是那么的多,畢竟很少有公司會(huì)吧之前的項(xiàng)目隨便更換某些必要的依賴(lài)的版本號(hào),除非迫不得已。

flatMap

其實(shí)這個(gè)方法,是真的不常用,因?yàn)槲覀冇玫降模芏喽际?nbsp;forEach ,或者 filter ,或者 map 這些都是我們比較常用的。

而 flatMap 相當(dāng)于 map+flat,通過(guò) map 把每一個(gè)元素替換為一個(gè)流,然后展開(kāi)這個(gè)流。比如,我們要統(tǒng)計(jì)所有訂單的總價(jià)格,可以有兩種方式:

就是 Order 里面有一個(gè) Detail 的信息,而這個(gè) Order 是一個(gè) List  而 Detail 也是一個(gè) List,就比如下面

public class Order {

private String id;

private List<Detail> details;

}

public class Order {

private String productId;

private Double productPrice;

private Integer productQuantity;

}

如果我們想要統(tǒng)計(jì)訂單總價(jià),如果 Order 表中已經(jīng)存在了這個(gè)價(jià)格這塊的內(nèi)容了,那當(dāng)然好,如果沒(méi)有,那么就得去匯總詳情了,不是么?

//求和使用flatMap
orders.stream().flatMap(order -> order.getDetails().stream()).mapToDouble(item -> item.getProductQuantity() * item.getProductPrice()).sum();


//求和使用flatMapToDouble
orders.stream().flatMapToDouble(order ->order.getDetails().stream().mapToDouble(item -> item.getProductQuantity() * item.getProductPrice())).sum();

其實(shí),了不起覺(jué)得,JDK8 中才是真的有很多了不起的內(nèi)容,再比如我們統(tǒng)計(jì)list中的數(shù)據(jù),已經(jīng)不在需要自己去做for循環(huán)來(lái)進(jìn)行比對(duì)了,而是直接通過(guò)方法來(lái)獲取。

//獲取最大
Integer id = userList.stream().map(User::getId).max(Integer::compareTo).get();
//獲取最小
Integer id1 = userList.stream().map(User::getId).min(Integer::compareTo).get();
//獲取id數(shù)量
long count = userList.stream().map(User::getId).count();
//總和
int sum = userList.stream().mapToInt(User::getId).sum();
//獲取平均值
double d = userList.stream().mapToInt(User::getId).average().getAsDouble();

分組統(tǒng)計(jì)

  //分組統(tǒng)計(jì)
    Map<String, Long> map = userList.stream().collect(Collectors.groupingBy(User::getName, Collectors.counting()));
  //分組 Collectors.groupingBy(屬性名)
 Map<Integer, List<Person>> map = list.stream().collect(Collectors.groupingBy(Person::getAge));
    //將名字全轉(zhuǎn)換為大寫(xiě)
    List<String> list = userList.stream().map(User::getName).map(String::toUpperCase).collect(Collectors.toList());
    //獲取忽略第一個(gè)并取前幾條數(shù)據(jù)
    List<User> list1 = userList.stream().skip(1).limit(2).collect(Collectors.toList());
    //distinct() 去重;collect(Collectors.toList())。封裝成集合
    List<User> collect = userList.stream().distinct().collect(Collectors.toList());

讀到這里,這篇“Java中不常用的開(kāi)發(fā)技巧有哪些”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識(shí)點(diǎn)還需要大家自己動(dòng)手實(shí)踐使用過(guò)才能領(lǐng)會(huì),如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI