实用小算法

使用小算法

	这个算法主要是用来处理两个数据集合的数据匹配问题。

比如有两个集合:

public class test01 {

    public static void main(String[] args) {
        // 老公组
        List<Couple> husbands = new ArrayList<>();
        husbands.add(new Couple(1, "梁山伯"));
        husbands.add(new Couple(2, "牛郎"));
        husbands.add(new Couple(3, "干将"));
        husbands.add(new Couple(4, "工藤新一"));
        husbands.add(new Couple(5, "罗密欧"));

        // 老婆组
        List<Couple> wives = new ArrayList<>();
        wives.add(new Couple(1, "祝英台"));
        wives.add(new Couple(2, "织女"));
        wives.add(new Couple(3, "莫邪"));
        wives.add(new Couple(4, "毛利兰"));
        wives.add(new Couple(5, "朱丽叶"));
	}
}

实体类:

public class Couple {

    private Integer familyId;
    private String userName;

    public Couple(Integer familyId, String userName) {
        this.familyId = familyId;
        this.userName = userName;
    }

    public Integer getFamilyId() {
        return familyId;
    }

    public void setFamilyId(Integer familyId) {
        this.familyId = familyId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }
}

现在有一个需求:
需要输出的格式为:
梁山伯爱祝英台
牛郎爱织女
干将爱莫邪
工藤新一爱毛利兰
罗密欧爱朱丽叶

第一种方法
直接循环
		int count=0;
        for (Couple h :husbands){
            for (Couple w :wives){
                count++;
                if (h.getFamilyId().equals(w.getFamilyId())){

                    System.out.println(h.getUserName()+"爱"+w.getUserName());
                }
            }
        }

这样数据的结果是

梁山伯爱祝英台
牛郎爱织女
干将爱莫邪
工藤新一爱毛利兰
罗密欧爱朱丽叶
25
第二种方法

一个丈夫只匹配到一个妻子,如果匹配到之后,就没有必要再去循环妻子们了

for (Couple h :husbands){
            for (Couple w :wives){
                count++;
                if (h.getFamilyId().equals(w.getFamilyId())){

                    System.out.println(h.getUserName()+"爱"+w.getUserName());
                    //如果丈夫匹配到妻子,就结束循环,换丈夫找妻子
                    break;
                }
            }
        }
梁山伯爱祝英台
牛郎爱织女
干将爱莫邪
工藤新一爱毛利兰
罗密欧爱朱丽叶
15
第三种方法
第一个丈夫匹配到妻子后,第二个丈夫还是会和匹配了丈夫的妻子进行比较,所以需要把匹配到的妻子删除掉
for (Couple h :husbands){
            for (Couple w :wives){
                count++;
                if (h.getFamilyId().equals(w.getFamilyId())){

                    System.out.println(h.getUserName()+"爱"+w.getUserName());
                    wives.remove(w);
                    //如果丈夫匹配到妻子,就结束循环,换丈夫找妻子
                    break;//如果这里不用break,会报错的
                }
            }
        }
梁山伯爱祝英台
牛郎爱织女
干将爱莫邪
工藤新一爱毛利兰
罗密欧爱朱丽叶
5
第四种方法
终极方法,如果给每一个女嘉宾发一个牌子,这样男嘉宾可以根据牌子直接找到女嘉宾
//给女嘉宾发牌子
        Map<Integer, Couple> map = new HashMap<>();
        for (Couple w :wives){
            map.put(w.getFamilyId(),w);
            count++;
        }
        //男嘉宾上场
        for (Couple h :husbands){
            Couple couple = map.get(h.getFamilyId());
            System.out.println(h.getUserName()+"爱"+couple.getUserName());
            count++;
        }
梁山伯爱祝英台
牛郎爱织女
干将爱莫邪
工藤新一爱毛利兰
罗密欧爱朱丽叶
10

问题:
上述第三种方法,删除集合元素会有问题,如果不用break的话,会ConcurrentModificationException(并发修改异常),因为增强for循环的底层是迭代器,迭代器的next()方法会检查并发修改异常(集合中的‘版本号’是否在遍历的过程中发生改变),对集合的元素进行增删的时候,会修改版本号。
而对于list,有两个遍历方式:
1.增强for循环(迭代器)
2.普通for循环,集合遍历元素
但是两者不能混用,第三种方法,就是混用了,所以会报异常
解决方法:
一.用迭代器遍历元素,用迭代器删除元素

//获取女嘉宾的迭代器
        Iterator<Couple> iterator = wives.iterator();
        for (Couple h :husbands){
            //遍历迭代器
            while (iterator.hasNext()){
                if (h.getFamilyId().equals(iterator.next().getFamilyId())){
                    System.out.println(h.getUserName()+"爱"+iterator.next().getUserName());
                    //删除元素
                    iterator.remove();
                }
            }
        }

二.用普通for循环进行遍历集合,删除集合

for (Couple h :husbands){
            for (int i=0;i<wives.size();i++){
                if (h.getFamilyId().equals(wives.get(i).getFamilyId())){
                    System.out.println(h.getUserName()+"爱"+wives.get(i).getUserName());
                    wives.remove(i);
                    i--;//集合里元素减少了一个
                    count++;
                }
            }
        }

ps:内容来源于 bravo1988 大神

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值