国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Java對(duì)象深拷貝詳解(List深拷貝)

這篇具有很好參考價(jià)值的文章主要介紹了Java對(duì)象深拷貝詳解(List深拷貝)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

1、Java中拷貝的概念

在Java語言中,拷貝一個(gè)對(duì)象時(shí),有淺拷貝與深拷貝兩種

淺拷貝:只拷貝源對(duì)象的地址,所以新對(duì)象與老對(duì)象共用一個(gè)地址,當(dāng)該地址變化時(shí),兩個(gè)對(duì)象也會(huì)隨之改變。

深拷貝:拷貝對(duì)象的所有值,即使源對(duì)象發(fā)生任何改變,拷貝的值也不會(huì)變化。

在User類的基礎(chǔ)上,介紹兩種淺拷貝案列

User類:

@Data
public class User {
    private String name;
    private Integer age;
}

案列①:普通對(duì)象的淺拷貝

package com.shuizhu.study;
//淺拷貝案例1
public class Study01 {
    public static void main(String[] args) {
        User user1 = new User();
        user1.setName("張三");
        user1.setAge(18);
        User user2 = user1;
        System.out.println("user1未改變前,user2的名字為:" + user2.getName());
        user1.setName("李四");
        System.out.println("user1未改變前,user2的名字為:" + user2.getName());
    }
}

結(jié)果:改變user1后,user2的值也隨之變化

java list 深拷貝,Java基礎(chǔ),java

案列②:List淺拷貝(這也是我們平時(shí)項(xiàng)目中,經(jīng)常遇到的情況)

package com.shuizhu.study;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

//Java淺拷貝案列2
public class Study02 {
    public static void main(String[] args) {
        List<User> list1 = new ArrayList<>();
        User user1 = new User();
        user1.setName("張三");
        user1.setAge(18);
        User user2 = new User();
        user2.setName("李四");
        user2.setAge(19);
        list1.add(user1);
        list1.add(user2);
        //TODO 以下是開發(fā)中,經(jīng)常發(fā)生的淺拷貝
        //方式1:通過new ArrayList方式,把list01拷貝給list02
        List<User> list2 = new ArrayList<>(list1);
        System.out.println("list1未改變前,list2的結(jié)果為:" + list2);

        //方式2:通過addAll方法,把list01拷貝給list02
        List<User> list3 = new ArrayList<>();
        list3.addAll(list1);
        System.out.println("list1未改變前,list3的結(jié)果為:" + list3);

        //方式3:通過stream流的方式,把list01拷貝給list02
        List<User> list4 = list1.stream().collect(Collectors.toList());
        System.out.println("list1未改變前,list4的結(jié)果為:" + list4);

        //改變list1集合中的user1對(duì)象
        System.out.println("--------------------------------------------");
        user1.setName("老六");
        user1.setAge(78);

        System.out.println("list1改變后,list2的結(jié)果為:" + list2);
        System.out.println("list1改變后,list3的結(jié)果為:" + list3);
        System.out.println("list1改變后,list4的結(jié)果為:" + list4);
    }
}

結(jié)果:對(duì)List的3種拷貝,其實(shí)都是淺拷貝,當(dāng)源集合中對(duì)象發(fā)生改變時(shí),新的List也會(huì)隨之變化

java list 深拷貝,Java基礎(chǔ),java

2、常見的深拷貝方式

  1. 構(gòu)造函數(shù)方式(new的方式)
  2. 重寫clone方法
  3. Apache Commons Lang序列化
  4. Gson序列化
  5. Jackson序列化

2.1、構(gòu)造函數(shù)方式

這種方式就是創(chuàng)建一個(gè)新的對(duì)象,然后通過源對(duì)象的get方法與新對(duì)象set方法,把源對(duì)象的值復(fù)制新對(duì)象,這里就不再演示了。

缺點(diǎn):在拷貝的對(duì)象數(shù)量較少時(shí),可以使用,但是對(duì)象數(shù)量過多時(shí),會(huì)大大增加系統(tǒng)開銷,開發(fā)中應(yīng)避免使用。

2.2、重寫clone方法

步驟:

1>需要拷貝對(duì)象的類,去實(shí)現(xiàn)Cloneable接口

2>重寫clone方法

3>使用"對(duì)象.clone()"的方式進(jìn)行拷貝

根據(jù)上面的案列,進(jìn)行對(duì)應(yīng)的改造:

首先是User實(shí)體類 ,如下:

@Data
public class User implements Cloneable{
    private String name;
    private Integer age;

    @Override
    protected User clone() throws CloneNotSupportedException {
        return (User) super.clone();
    }
}

改造案列①:

package com.shuizhu.study;
//Java深拷貝案列
public class Study03 {
    public static void main(String[] args) throws CloneNotSupportedException {
        User user1 = new User();
        user1.setName("張三");
        user1.setAge(18);
        User user2 = user1.clone();
        System.out.println("user1未改變前,user2的名字為:" + user2.getName());
        user1.setName("李四");
        System.out.println("user1未改變前,user2的名字為:" + user2.getName());
    }
}

結(jié)果:當(dāng)user1改變后,user2的值不會(huì)改變

java list 深拷貝,Java基礎(chǔ),java

改造案列②:List類型深拷貝

package com.shuizhu.study;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

//Java深拷貝案列
public class Study04 {
    public static void main(String[] args) {
        List<User> list1 = new ArrayList<>();
        User user1 = new User();
        user1.setName("張三");
        user1.setAge(18);
        User user2 = new User();
        user2.setName("李四");
        user2.setAge(19);
        list1.add(user1);
        list1.add(user2);
        /
        //通過clone方式,把list01拷貝給list02
        List<User> list2 = new ArrayList<>();  
        //TODO 當(dāng)數(shù)據(jù)量多時(shí),建議使用對(duì)象的方式,把List當(dāng)做屬性,然后拷貝哦到一個(gè)新的對(duì)象中,從而不需要循環(huán),可以見Apache Commons Lang序列化深拷貝方式
        list1.forEach(user->{
            try {
                list2.add(user.clone());
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
        });
        System.out.println("list1未改變前,list2的結(jié)果為:" + list2);
        
        //改變list1集合中的user1對(duì)象
        System.out.println("--------------------------------------------");
        user1.setName("老六");
        user1.setAge(78);

        System.out.println("list1改變后,list2的結(jié)果為:" + list2);
    }
}

結(jié)果:list1中的每個(gè)對(duì)象通過clone()添加list2中,當(dāng)list1中的對(duì)象改變時(shí),list2不會(huì)改變

java list 深拷貝,Java基礎(chǔ),java

2.3 、Apache Commons Lang序列化

步驟:

1>導(dǎo)入Commons包

<dependency>
   <groupId>org.apache.commons</groupId>
   <artifactId>commons-lang3</artifactId>
   <version>3:3.5</version>
</dependency>

2>實(shí)體類實(shí)現(xiàn)Serializable接口

@Data
public class User implements Serializable {
    private String name;
    private Integer age;
}

3>調(diào)用SerializationUtils工具類,實(shí)現(xiàn)深拷貝(注意:SerializationUtils不能直接拷貝List類型)

案列如下:

案列①:對(duì)象深拷貝

package com.shuizhu.study2;
import org.apache.commons.lang3.SerializationUtils;

//Apache Commons Lang序列化實(shí)現(xiàn)對(duì)象的深拷貝
public class Study01 {
    public static void main(String[] args) {
        User user1 = new User();
        user1.setName("張三");
        user1.setAge(18);
        User user2 = SerializationUtils.clone(user1);
        System.out.println("user1未改變前,user2的名字為:" + user2.getName());
        user1.setName("李四");
        System.out.println("user1改變后,user2的名字為:" + user2.getName());
    }
}

結(jié)果:user1的改變不會(huì)導(dǎo)致user2的改變,從而實(shí)現(xiàn)深拷貝

java list 深拷貝,Java基礎(chǔ),java?

案列②:List類型深拷貝

(1)改造開始,我們先創(chuàng)建一個(gè)專門用于拷貝List<User>類型的實(shí)體類

package com.shuizhu.study2;

import java.io.Serializable;
import java.util.List;

/**
 * @author 睡竹
 * @date 2022/12/10
 * 用于深拷貝時(shí),不需要去遍歷List<User>集合,只需要拷貝UserCopyDTO 對(duì)象就可以
 * 獲取到新的List<User>集合
 */
@Data
public class UserCopyDTO implements Serializable {//必須實(shí)現(xiàn)Serializable接口
    private List<User> users;
}

(2)拷貝List類型

package com.shuizhu.study2;

import org.apache.commons.lang3.SerializationUtils;

import java.util.ArrayList;
import java.util.List;

//Apache Commons Lang序列化實(shí)現(xiàn)List的深拷貝
public class Study02 {
    public static void main(String[] args) {
        List<User> list1 = new ArrayList<>();
        User user1 = new User();
        user1.setName("張三");
        user1.setAge(18);
        User user2 = new User();
        user2.setName("李四");
        user2.setAge(19);
        list1.add(user1);
        list1.add(user2);

        //使用UserCopyDTO對(duì)象,專門用于拷貝List<User>類型數(shù)據(jù),不需要再去遍歷list1 
        UserCopyDTO userCopyDTO = new UserCopyDTO();
        userCopyDTO.setUsers(list1);
        //通過Apache Commons Lang序列化方式,把list01拷貝給list02
        UserCopyDTO clone = SerializationUtils.clone(userCopyDTO);
        List<User> list2 = clone.getUsers();
        System.out.println("list1未改變前,list2的結(jié)果為:" + list2);

        //改變list1集合中的user1對(duì)象
        System.out.println("--------------------------------------------");
        user1.setName("老六");
        user1.setAge(78);
        System.out.println("list1改變后,list2的結(jié)果為:" + list2);

    }
}

結(jié)果:

java list 深拷貝,Java基礎(chǔ),java

?2.4、Gson序列化

步驟:

1、導(dǎo)入Gson依賴

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.5</version>
</dependency>

2>創(chuàng)建Gson對(duì)象,使用該對(duì)象進(jìn)行深拷貝(實(shí)體類不再需要實(shí)現(xiàn)Serializable接口)

案例如下:只演示對(duì)象的深拷貝,LIst類型的深拷貝與之前的流程是相似的

package com.shuizhu.study3;
import com.google.gson.Gson;

//Gson序列化實(shí)現(xiàn)對(duì)象的深拷貝
public class Study01 {
    public static void main(String[] args) {
        User user1 = new User();
        user1.setName("張三");
        user1.setAge(18);
        Gson gson = new Gson();
        User user2 = gson.fromJson(gson.toJson(user1), User.class);
        System.out.println("user1未改變前,user2的名字為:" + user2.getName());
        user1.setName("李四");
        System.out.println("user1改變后,user2的名字為:" + user2.getName());
    }
}

重點(diǎn):

java list 深拷貝,Java基礎(chǔ),java

結(jié)果:

java list 深拷貝,Java基礎(chǔ),java?

?2.5、Jackson序列化

該方式與Gson原理、使用方式相似,但是Jackson序列化深拷貝,要求拷貝的對(duì)象必須有無參構(gòu)造函數(shù)

步驟:

1>導(dǎo)入Jackson依賴

<dependency>
    <groupId>com.fasterxml.jackson</groupId>
    <artifactId>core</artifactId>
    <version>2.2.2</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson</groupId>
    <artifactId>databind</artifactId>
    <version>2.2.2</version>
</dependency>

2>創(chuàng)建ObjectMapper對(duì)象,進(jìn)行深拷貝(用法與Gson一致)

package com.shuizhu.study4;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;

//Jackson序列化實(shí)現(xiàn)對(duì)象的深拷貝
public class Study01 {
    public static void main(String[] args) {
        User user1 = new User();
        user1.setName("張三");
        user1.setAge(18);
        ObjectMapper mapper = new ObjectMapper();
        User user2 = null;
        try {
            user2 = mapper.readValue(mapper.writeValueAsString(user1), User.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("user1未改變前,user2的名字為:" + user2.getName());
        user1.setName("李四");
        System.out.println("user1改變后,user2的名字為:" + user2.getName());
    }
}

重點(diǎn):

java list 深拷貝,Java基礎(chǔ),java

結(jié)果:

java list 深拷貝,Java基礎(chǔ),java?

3、總結(jié)

方式 優(yōu)點(diǎn) 缺點(diǎn)
構(gòu)造函數(shù) 1. 底層實(shí)現(xiàn)簡單 2. 不需要引入第三方包 3. 系統(tǒng)開銷小 4. 對(duì)拷貝類沒有要求,不需要實(shí)現(xiàn)額外接口和方法 1. 可用性差,每次新增成員變量都需要新增新的拷貝構(gòu)造函數(shù)
重載clone()方法

1. 底層實(shí)現(xiàn)較簡單 2. 不需要引入第三方包 3. 系統(tǒng)開銷小

追求性能的可以采用該方式

1. 可用性較差,每次新增成員變量可能需要修改clone()方法 2. 拷貝類(包括其成員變量)需要實(shí)現(xiàn)Cloneable接口
Apache Commons Lang序列化 1. 可用性強(qiáng),新增成員變量不需要修改拷貝方法 1. 底層實(shí)現(xiàn)較復(fù)雜 2. 需要引入Apache Commons Lang第三方JAR包 3. 拷貝類(包括其成員變量)需要實(shí)現(xiàn)Serializable接口 4. 序列化與反序列化存在一定的系統(tǒng)開銷
Gson序列化 1. 可用性強(qiáng),新增成員變量不需要修改拷貝方法 2. 對(duì)拷貝類沒有要求,不需要實(shí)現(xiàn)額外接口和方法 1. 底層實(shí)現(xiàn)復(fù)雜 2. 需要引入Gson第三方JAR包 3. 序列化與反序列化存在一定的系統(tǒng)開銷
Jackson序列化 1. 可用性強(qiáng),新增成員變量不需要修改拷貝方法 1. 底層實(shí)現(xiàn)復(fù)雜 2. 需要引入Jackson第三方JAR包 3. 拷貝類(包括其成員變量)需要實(shí)現(xiàn)默認(rèn)的無參構(gòu)造函數(shù) 4. 序列化與反序列化存在一定的系統(tǒng)開銷

?文章來源地址http://www.zghlxwxcb.cn/news/detail-781085.html

?

?

?

?

到了這里,關(guān)于Java對(duì)象深拷貝詳解(List深拷貝)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 對(duì)java中的List進(jìn)行深拷貝,并進(jìn)行刪除測(cè)試

    ListString list = new ArrayList();? // 需要拷貝的原始List list.add(\\\"aaa\\\"); list.add(\\\"bbb\\\"); list.add(\\\"ccc\\\"); ListString listNew = new ArrayList();? // 新List // 將原始List的值賦值給新List CollectionUtils.mergeArrayIntoCollection(new Object[list.size()], listNew); Collections.copy(listNew, list); // 現(xiàn)在將心List中的值刪除一個(gè),會(huì)

    2024年02月11日
    瀏覽(16)
  • 【Java List與對(duì)象】List<T>對(duì)象和對(duì)象List<T>的區(qū)別(125)

    List<T>對(duì)象 :對(duì)象里面的元素屬性包含List<T>(只有一個(gè)對(duì)象); 對(duì)象List<T> :List<T>里面的數(shù)據(jù)是對(duì)象類型(可以有多組對(duì)象,但必須是同一個(gè)類型); 測(cè)試案例: Book類: Student類: 測(cè)試Demo : ( 重點(diǎn) ) 測(cè)試輸出 :

    2024年02月11日
    瀏覽(18)
  • Java List對(duì)象集合轉(zhuǎn)Json & Json轉(zhuǎn)List對(duì)象集合

    使用了阿里巴巴的 fastjson ?首先引入依賴 示例如下 輸出結(jié)果:

    2024年02月15日
    瀏覽(18)
  • java8利用Stream方法求兩個(gè)List對(duì)象的交集、差集與并集(即:anyMatch和allMatch和noneMatch的區(qū)別詳解)

    1、anyMatch? 判斷數(shù)據(jù)列表中是否存在任意一個(gè)元素符合設(shè)置的predicate條件,如果是就返回true,否則返回false。 接口定義: boolean anyMatch(Predicate? super T predicate); 方法描述: 在anyMatch 接口定義中是接收 Predicate 類型參數(shù),在Lamdba表達(dá)式中 PredicateT 是接收一個(gè)T類型參數(shù),然后經(jīng)過

    2024年02月06日
    瀏覽(92)
  • 【java】List對(duì)象集合去除特定對(duì)象的優(yōu)雅寫法(基于java8)

    【java】List對(duì)象集合去除特定對(duì)象的優(yōu)雅寫法(基于java8) 主要用的是 Java List.removeIf方法,該方法用于刪除所有滿足特定條件的數(shù)組元素,入?yún)⑵鋵?shí)是一個(gè)布爾值的表達(dá)式即可。 使用場(chǎng)景,用戶類中的性別字段有三個(gè),分別是男、女、未知。 當(dāng)前端要查詢:“男”時(shí),要求

    2024年02月16日
    瀏覽(91)
  • <Java工具類>json字符串、List Map,List 對(duì)象轉(zhuǎn)換為相應(yīng)的JavaBean對(duì)象

    依賴: 工具類(直接上代碼): 使用場(chǎng)景: (1).使用泛型方法:把json字符串轉(zhuǎn)換為相應(yīng)的JavaBean對(duì)象 ; 一般用于:Controller層: 例如: (2).List Map轉(zhuǎn)換List 對(duì)象:如List,將第二個(gè)參數(shù)傳遞為Student對(duì)象; (3).List 對(duì)象轉(zhuǎn)換List Map:

    2024年02月12日
    瀏覽(29)
  • java List<對(duì)象> 根據(jù)對(duì)象的一個(gè)屬性進(jìn)行去重

    1.實(shí)現(xiàn)一個(gè)自定義函數(shù),該函數(shù)將用于確定兩個(gè)對(duì)象是否相等,例如: 這個(gè)函數(shù)接受一個(gè)Function對(duì)象作為參數(shù),該函數(shù)將從對(duì)象中提取唯一標(biāo)識(shí)屬性,并使用ConcurrentHashMap來確定是否已經(jīng)處理過該屬性值。? ?2.現(xiàn)在你可以使用這個(gè)函數(shù)來進(jìn)行去重了,例如: ?這個(gè)代碼將對(duì)m

    2024年02月12日
    瀏覽(19)
  • java 對(duì)象List中對(duì)象的某一屬性重新賦值

    描述: 在我們開發(fā)過程中經(jīng)常會(huì)遇到在拿到一個(gè)對(duì)象list集合的時(shí)候回對(duì)某一個(gè)字段重新賦值,比如:在無任務(wù)下面的若干子任務(wù),開始執(zhí)行主任務(wù)對(duì)子任務(wù)的狀態(tài)統(tǒng)一設(shè)置待執(zhí)行。這個(gè)時(shí)候就需要使用 Java8 stream 或者 List forEach 這兩種方式來實(shí)現(xiàn),方便快捷,也不需要再遍歷

    2024年02月12日
    瀏覽(32)
  • Java8 stream、List forEach 遍歷對(duì)象 List 對(duì)某一字段重新賦值

    Java8 stream、List forEach 遍歷對(duì)象 List 對(duì)某一字段重新賦值 經(jīng)常會(huì)需要遍歷對(duì)象 List 對(duì)某一字段重新賦值,使用 Java8 stream 或者 List forEach 操作實(shí)現(xiàn)非常便捷。 一、Java8 stream 操作 示例代碼如下: 二、List forEach 操作 示例代碼如下: 將 Object 替換為需要提取的對(duì)象即可。 遍歷對(duì)象

    2024年02月16日
    瀏覽(24)
  • JAVA 使用stream流將List中的對(duì)象某一屬性創(chuàng)建新的List

    Java Stream是Java 8引入的一種新機(jī)制,它可以讓我們以聲明式方式操作集合數(shù)據(jù),提供了更加簡潔、優(yōu)雅的集合處理方式。Stream是一個(gè)來自數(shù)據(jù)源的元素隊(duì)列,并支持聚合操作。它的特點(diǎn)有: Stream 不會(huì)修改原始數(shù)據(jù)源。 Stream 操作是延遲執(zhí)行的。 Stream 操作可以是無限的(比如

    2024年02月03日
    瀏覽(93)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包