梦回苍石居  |
Cangshi Live

关于Apex 中 Set 去重的 Issue - Winter’21

APEXSALESFORCE
苍石 发表于:2019-07-09 15:15:35  最后编辑于:4 年前 70 Views

关于Apex 中 Set 去重的 Issue - Winter’21

描述

使用 Apex 中的 Set 时,添加一个相同地址的对象时,无论添加多少次理应只有一个对象存在。但在实际操作中,如果在每次添加前改动对象的一些属性,这次添加后的 Set 在未访问的情况下,同时存在该对象的多个元素,和 List 一样。但如果你访问了该 Set (调用 toString 方法),其包含的元素才会被去重。

e.g.

Set<Account> accounts = new Set<Account>();
Account account = new Account(Name = 'Test Account');

accounts.add(account);

// First changed
account.Phone = '100001';
accounts.add(account);

// The second time changed
account.Phone = '100002';
accounts.add(account);

// System.debug(accounts); // If there is no comment, the next line output of the set is: 3
// In the case of doing comment the previous line out, the output is: 1
System.debug(accounts.size());
Integer hashCode2 = accounts.hashCode();

// In this case, the annotated case is a list containing three elements, and the uncommented case is a list containing one element
System.debug(new List<Account>(accounts)); 

解决方法

  1. 通过 new Set() 将该 Set 作为参数传入构造方法中
    Set<Account> finalSet = new Set<Account>(accounts);
    
  2. 通过新建 Set 对象的 addAll 方法重建一个新的 Set
    Set<Account> finalSet = new Set<Account>();
    finalSet.addAll(accounts);
    

可能导致的原因

由于 Apex 底层是基于 Java 可能在 ListSet 的实现上是通过 Iterator 实现的,所以其内部可能都是允许放置多个重复的对象的,在使用 add 或其它方法添加对象一个对象时,可能只对 hash 值进行检查,在以上例子中,由于哈希值改变了,便成功添加到了内部列表,而在 Set 在读取的时候(使用 toString 等方法 ),会对内部对象列表根据内存地址进行去重,所以导致如果 Set 对象没有被读取,其内部依然会存在多个相同的对象。

文章评论 ( 0 )

Person name
未登录用户可以发表匿名评论