JAVA TreeSet 有序集合是自然顺序而不是插入顺序(此有序非彼有序)

 

我之前写了一个代码;

大致的逻辑就是

有TreeSet long 和TreeSet short

两者遍历后,在long中剔除short的所有元素,剩余元素为2

然后将剩余元素拼接为字符串return。

 

结果发现了一个bug:return出来的字符串的值是乱序的。

仔细查了半天,发现我有这么一句话addAll(adjset.get(idlong));

百度了一下发现了一个深坑,addAll方法是不保留顺序的...

https://www.breakyizhan.com/java/4919.html



Map<Integer, TreeSet<Integer>> adjset = new HashMap<>();

TreeSet<Integer> longsidset = new TreeSet<>();
longsidset.addAll(adjset.get(idlong));

TreeSet<Integer> shortsidset = new TreeSet<>();
for (Integer item:adjset.get(idshort))
{shortsidset.add( item);}

TreeSet<Integer> subsidset = new TreeSet<>();
for (Integer item:adjset.get(idlong))
{subsidset.add( item);}

for (int item : shortsidset) {
    subsidset.remove(item);
}


if (subsidset.size() == 2) { ....}

 

进一步向下排查:

发现我还使用了

List<LinkedHashMap<String, String>> model_List2 = new ArrayList<>();

https://blog.csdn.net/Canxue_java/article/details/83625492

https://blog.csdn.net/wang_8101/article/details/83067860

https://segmentfault.com/q/1010000011429429/

经过排查,ArrayList确实也是有序列表没有问题。

LinkedHashMap是HashMap的子类,但是内部还有一个双向链表维护键值对的顺序,每个键值对既位于哈希表中,也位于双向链表中。LinkedHashMap支持两种顺序插入顺序 、 访问顺序

于是,修改了第一处后重新跑数据,结果发现,数据还是异常。

System.out.println()的结果为listlong="13403|32881|64682|68845" 依旧不是原始的数值序列。

经过进一步排查,发现在做split时,赋值对象是

String[] splitAddress = StringtoSplit.split("\\|");

https://blog.csdn.net/qq_33774822/article/details/83188727

打印了一下,发现也是有序列表。还不是这个原因。

 

经过深刻排查最后重要找到了原因:

”TreeSet是依靠TreeMap来实现的。 TreeSet是一个有序集合,TreeSet中的元素将按照升序排列,缺省是按照自然排序进行排列“

所以会自动按从小到大排列。

所以需要改为ArrayList

 

另外改成List以后就不能很方便的

for item : Set {set.remove(item)}了

 

需要改为

for (int il = 0;il < subset.size();il++) {
    for (int is = 0;is < shortsidset.size();is++){
        if (subsidset.get(il).equals(shortsidset.get(is))){
            subsidset.remove(il);
            break;
        }
    }
}

 

 List 删除元素的逻辑是将目标元素之后的元素往前移一个索引位置,最后一个元素置为 null,同时 size - 1

http://java.tedu.cn/data/406157.html

更好的办法是使用Iterator

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值