一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

022:如果要將對象用作Map中的key,需要注意什么

 liang1234_ 2020-02-17

參考答案

如果將對象作為Map中的key,需要是實(shí)現(xiàn)該對象的equals方法和hashCode方法;現(xiàn)在一般通過lombok可以簡單得實(shí)現(xiàn),并且可以選擇具體需要哪些字段參與equals和hashCode方法的計(jì)算。

知識點(diǎn)梳理

Java類型系統(tǒng)中分為基礎(chǔ)類型和引用類型,引用類型中所有的對象都有一個父類——java.lang.Object?;怬bject提供了一些可擴(kuò)展的方法:equals、hashCode、toString、clone和finalize。開發(fā)者在覆蓋這些方法的時候,要遵循一定的約定,如果使用不當(dāng)就會造成bug。

equals方法

如果類有自己的“邏輯相等”概念,而且父類的equals方法又無法滿足期望的時候,就應(yīng)該覆蓋equals方法。在開發(fā)中我們有時候會將一個自定義的對象作為map中的key,或者將一個自定義的對象加入到集合中,這時候就需要覆蓋equals方法。

hashCode方法

覆蓋equals方法的時候,要同時覆蓋hashCode方法。這里一起看一個案例。假設(shè)我定義一個用戶信息類,代碼如下所示:

import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(exclude = {"phoneNumber", "nickName", "sign", "address", "avatarUrl"})
public class UserInfo {

    private long userId;

    private String phoneNumber;

    private String nickName;

    private String sign;

    private String address;

    private String avatarUrl;
}

這里使用@EqualsAndHashCode注解生成equals和hashCode方法,并排除了除userId以外的其他字段,表示該用戶信息對象的唯一性只跟userId這個字段有關(guān)。如果該類是繼承了某個自定義的類,需要考慮父類的字段,那么還可以使用@EqualsAndHashCode中的callSuper字段,設(shè)置為true就會連父類的字段一起考慮,默認(rèn)是只考慮當(dāng)前類中的字段。關(guān)注lombok的用法,這里不展開講了。

假設(shè)有一個場景,需要過濾確保某個列表里的用戶對象是沒有重復(fù)的,那么我們就需要確定用戶對象的唯一id是什么?在這里是userId,可以使用集合來進(jìn)行重復(fù)對象的過濾,代碼如下所示:

import java.util.HashSet;
import java.util.Set;

public class ObjectExample {
    public static void main(String[] args) {
        UserInfo userInfo1 = new UserInfo();
        userInfo1.setAddress("abc");
        userInfo1.setAvatarUrl("http://");
        userInfo1.setNickName("aaa");
        userInfo1.setPhoneNumber("1768909876");
        userInfo1.setSign("");
        userInfo1.setUserId(289976L);

        UserInfo userInfo2 = new UserInfo();
        userInfo2.setAddress("abc");
        userInfo2.setAvatarUrl("http://");
        userInfo2.setNickName("aaa");
        userInfo2.setPhoneNumber("1768909876");
        userInfo2.setSign("");
        userInfo2.setUserId(289978L);

        UserInfo userInfo3 = new UserInfo();
        userInfo3.setAddress("abcddddd");
        userInfo3.setAvatarUrl("http://");
        userInfo3.setNickName("aaadddd");
        userInfo3.setPhoneNumber("176890999996");
        userInfo3.setSign("xxxxx");
        userInfo3.setUserId(289978L);

        Set<UserInfo> userInfoSet = new HashSet<UserInfo>();
        userInfoSet.add(userInfo1);
        userInfoSet.add(userInfo2);
        userInfoSet.add(userInfo3);

        System.out.println(userInfoSet.size());
    }
}

這個案例的執(zhí)行結(jié)果也很明顯,輸出的值是:2。

toString方法

所有自定義的類都要覆蓋toString方法,我會使用lombok的@ToString注解來幫我生成toString方法。使用toString方法可以將對象的字段都以可讀的形式展示出來。這樣在打印日志的時候,要打印某個對象,就不會打印出一個對象的地址,類似于UserInfo@1768b4。

clone方法

我在開發(fā)中沒有用過這個方法。要完成對象的拷貝,只需要區(qū)分自己是要深拷貝還是淺拷貝。一般我會使用拷貝構(gòu)造器或靜態(tài)工廠方法作為替代方案。

public UserInfo(UserInfo userInfo);

public static UserInfo newInstance(UserInfo userInfo)

finalize方法

根據(jù)Java問到,finalize方法被設(shè)計(jì)出來是用于釋放非Java資源,但是由于jvm的運(yùn)行機(jī)制導(dǎo)致有很大可能不會調(diào)用到對象的finalize方法,或者調(diào)用的時機(jī)和順序是不確定的,所以這個方法并沒有達(dá)到其設(shè)計(jì)目標(biāo)。Java9中這個方法已經(jīng)被廢棄了,不過現(xiàn)在很多面試還是會問到這個方法背后的原理,需要理解幾個概念:

  • 自定義類的對象,就是我們自定義的類,該類覆蓋了finalize方法
  • Finalizer對象,在新建一個覆蓋了finalize方法的類的對象的時候,就會伴生一個Finalizer對象,并將該對象加入到一個雙向列表中
  • 雙向列表:ReferenceQueue<Object> queue,F(xiàn)inalizer對象創(chuàng)建出來后,就會被加入到這個雙向列表
  • FinalizerThread對象,F(xiàn)inalizer線程是3號線程,它的作用就是不斷從上面哪個隊(duì)列中取Finalizer對象,然后調(diào)用它的runFinalzier方法。

在Java應(yīng)用中,如果對finalize方法使用不合理,有時候會引發(fā)一類問題——Finalizer隊(duì)列過長,導(dǎo)致一些對象的finalze方法調(diào)用延遲,如果程序在這個方法中進(jìn)行了某些對時間敏感的資源的釋放,那么就會有問題。

參考資料

  1. 《Effective Java中文版(2)》
  2. finalize方法
  3. 深入分析Object.finalize方法的實(shí)現(xiàn)原理
  4. https://www./java-finalize
  5. https:///questions/5175811/finalize-method-in-java

本號專注于后端技術(shù)、JVM問題排查和優(yōu)化、Java面試題、個人成長和自我管理等主題,為讀者提供一線開發(fā)者的工作和成長經(jīng)驗(yàn),期待你能在這里有所收獲。


javaadu

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    国产又大又猛又粗又长又爽| 国产又粗又硬又长又爽的剧情| 亚洲一级二级三级精品| 欧美精品一区二区三区白虎| 成人免费视频免费观看| 国产成人国产精品国产三级| 日本中文字幕在线精品| 亚洲精品中文字幕熟女| 日韩欧美一区二区亚洲| 亚洲伦理中文字幕在线观看| 日韩精品第一区二区三区| 国产又黄又猛又粗又爽的片| 国产精品免费视频视频| 殴美女美女大码性淫生活在线播放| 日韩欧美综合中文字幕| 中文字幕乱子论一区二区三区| 久久国内午夜福利直播| 亚洲婷婷开心色四房播播| 色偷偷偷拍视频在线观看| 天海翼高清二区三区在线| 国产精品熟女在线视频| 日韩中文字幕欧美亚洲| 日韩视频在线观看成人| 九九久久精品久久久精品| 亚洲成人精品免费在线观看| 色婷婷中文字幕在线视频| 91日韩欧美中文字幕| 高中女厕偷拍一区二区三区| 麻豆在线观看一区二区| 日韩高清一区二区三区四区| 99久久精品久久免费| 人人妻人人澡人人夜夜| 亚洲一区二区三区三州| 亚洲性日韩精品一区二区| 极品少妇一区二区三区精品视频| 激情丁香激情五月婷婷| 大香蕉再在线大香蕉再在线| 国产精品国三级国产专不卡| 国产精品丝袜一二三区| 亚洲国产成人爱av在线播放下载| 美女被后入视频在线观看|