zl程序教程

您现在的位置是:首页 >  Java

当前栏目

数组的拷贝

2023-02-18 16:39:24 时间

数组的拷贝

背景

一个数组中有多个map,要重复操作在map中插入个随机数,把map存到新的数组中,发现会有相同的map

@Test
    public void test4() {
        Random r = new Random();
        List<Map<String, Object>> l = new ArrayList<>();
        List<Map<String, Object>> l1 = new ArrayList<>();
        Map<String, Object> m = new HashMap<>();
        m.put("a", "1");
        Map<String, Object> m1 = new HashMap<>();
        m1.put("a", "2");
        l1.add(m);
        l1.add(m1);
        for (int i = 0; i < 3; i++) {
            for (Map<String, Object> b : l1) {
                int t = r.nextInt(1000);
                b.put("c", t);

                System.out.println(t);
            }
            l.addAll(l1);
        }

        System.out.println(l);

    }

输出结果:

851
543
204
668
108
347
[{a=1, c=108}, {a=2, c=347}, 
 {a=1, c=108}, {a=2, c=347}, 
 {a=1, c=108}, {a=2, c=347}]

尽管每次插入的随机数不同,但是发现结果是重复的,因为循环操作了同一个数组l1,而数组l中保存的是l1的地址(l.addAll(l1);)导致最后的结果是3组相同的数据。

解决方案:新建一个数组l2去接收数组l1的数据,每次操作新数组,实现数据隔离

方案一:List.addAll()(浅拷贝)

List<Map<String, Object>> l2 = new ArrayList<>();
l2.addAll(l1);

方案二:使用List的构造方法(浅拷贝)

List<Map<String, Object>> l2 = new ArrayList<>(l1);
@Test
    public void test5() {
        Random r = new Random();
        List<Map<String, Object>> l = new ArrayList<>();
        List<Map<String, Object>> l1 = new ArrayList<>();
        Map<String, Object> m = new HashMap<>();
        m.put("a", "1");
        Map<String, Object> m1 = new HashMap<>();
        m1.put("a", "2");
        l1.add(m);
        l1.add(m1);
        for (int i = 0; i < 3; i++) {
            // 方案一
//            List<Map<String, Object>> l2 = new ArrayList<>();
//            l2.addAll(l1);
            // 方案二
            List<Map<String, Object>> l2 = new ArrayList<>(l1);

            
            for (Map<String, Object> b : l2) {
                int t = r.nextInt(1000);
                b.put("c", t);

                System.out.println(t);
            }

            l.addAll(l2);
        }

        System.out.println(l);

    }

输出结果还是重复的数据

751
812
509
957
512
874
[{a=1, c=512}, {a=2, c=874}, 
 {a=1, c=512}, {a=2, c=874}, 
 {a=1, c=512}, {a=2, c=874}]

打印JSONObject.toJSONString()打印结果会发现还是相同的地址引用

System.out.println(JSONObject.toJSONString(l));

结果:

[{"a":"1","c":995},{"a":"2","c":946},
 {"$ref":"$[0]"},{"$ref":"$[1]"},
 {"$ref":"$[0]"},{"$ref":"$[1]"}]

方案三:数据类型转换(深拷贝)

@Test
    public void test6() {
        Random r = new Random();
        List<Map<String, Object>> l = new ArrayList<>();
        List<Map<String, Object>> l1 = new ArrayList<>();
        Map<String, Object> m = new HashMap<>();
        m.put("a", "1");
        Map<String, Object> m1 = new HashMap<>();
        m1.put("a", "2");
        l1.add(m);
        l1.add(m1);
        for (int i = 0; i < 3; i++) {
            // 方案三,转成String,在转回List
            String str = JSONObject.toJSONString(l1);
            List<Map<String, Object>> l2 = JSONObject.parseObject(str, List.class);
            
            for (Map<String, Object> b : l2) {
                int t = r.nextInt(1000);
                b.put("c", t);

                System.out.println(t);
            }

            l.addAll(l2);
        }

        System.out.println(l);

    }

测试发现数据没有重复,实现数据隔离

941
685
901
129
449
516
[{"a":"1","c":941}, {"a":"2","c":685}, 
 {"a":"1","c":901}, {"a":"2","c":129}, 
 {"a":"1","c":449}, {"a":"2","c":516}]

当然还有其他序列化方式的深度拷贝都能实现数据隔离,之后在补充