由一道java题的思考和引申

题目:

用程序产生10个随机数,序号从1到10,然后对这10个数进行从小到大排序,并输出这10个数和相对应的序号


解决方案:

一、数组法
使用两个数组,分别存储随机数和序号,按随机数排序同时移动序号数组。但是需要自己写排序法(如冒泡法),在java环境下自己写排序法是不高明的,而且同时移动两个数组效率也不高。

二、Map法
key为随机数,value为序号。但是随机数相同即生成相同的key(违反Map定义)则会产生麻烦。

三、字符串法(自己想的名字,呵呵)
思路:将随机数和序号组成字符串(如随机数78序号1->78:1),将所有随机数放入List中,然后重写Collection.sort()方法,截取字符串的第0位到":",按照数字排序即可。代码如下:

public static void main(String[] args) { List <String> listSeqAndNum = new ArrayList <String>(); for(int i=0;i<10;i++) { listSeqAndNum.add((int)(Math.random()*100)+":"+(i+1)); } outputList(listSeqAndNum); Collections.sort(listSeqAndNum , new Comparator<String>(){ public int compare(String a, String b) { int orderA = Integer.parseInt(a.substring(0, a.indexOf(":"))); int orderB = Integer.parseInt( b.substring(0, b.indexOf(":"))); return orderA - orderB; } }); System.out.println("============================="); outputList(listSeqAndNum); } public static void outputList(List<String> list) { for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) { System.out.println(iterator.next()); } }


思考过程:

第一种方法应该是大家最先想到的,使用数组存储数据,然后使用各种排序法进行排序,其实此题的关键处不只是排序,而是另一个关键点建立关联,即集合A(随机数)与集合B(序号)的一一对应关系。

因此大多数人会想到第二种方法,使用Map的key-value对应关系,但是将谁设置为key呢,首先将随机数设置为key,这样可以将随机数排序后,通过Map.get()方法获得对应的序号,到此感觉大功告成了,其实忽略了一个问题,就是潜意识中认为随机数的产生不会出现重复(随机数重复是很有可能形成的),所以当随机数重复时,违反了map的定义,Java会将原来的值(序号)覆盖掉,产生错误。那让序号作为key呢(我们不愿意放弃这个现成的集合对应数据结构Map),序号肯定是不会重复的(从1到10嘛),将value排序吧,然后通过value找到对应的序号,感觉没问题了,那我们再来讨论一下重复随机数的问题,value允许重复,但是能通过重复的value找到对应key吗,肯定是不行了,通过java提供的方法也可以证明这一点,只有Map.get(key);方法得到value,没有Map.get(value);得到key的。Map暂时放弃了!

既然关键点在于建立关联,那还不如就把随机数和序号放一起呢,这样就避免了关联的这个关键点,使用字符串就OK了,只排序字符串就可以了,但是字符串的排序是按照ASCII排序的所以9会排在10的后面,所以需要重写Collection.sort()方法,截取字符串的第0位到":",按照数字规则排序即可,这就是第三种方法。


引申:

Map的针对性与集合

这道题表面上是一对一的关系,其实它隐藏的却是一个多对一的关系,即多个序号对应一个随机数(假设集合中没有重复的元素),所以导致的Map的失效。

那有什么可以实现这个一对多的功能呢?

未完待续......


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值