背景
之前有个位朋友给我了一看了一段代码,大致意思是给一个列表,里面元素是人,需要将一个列表的用户随机分成两拨人,关键词是“随机”
List<String> allPerson = new ArrayList<String>(); allPerson.add("何XX"); allPerson.add("李XX"); allPerson.add("屈XX"); allPerson.add("刘XX"); allPerson.add("王XX"); allPerson.add("涂XX"); allPerson.add("张XX"); allPerson.add("方XX"); allPerson.add("何XX"); allPerson.add("周XX"); List<String> aGroup = new ArrayList<String>(); List<String> bGroup = new ArrayList<String>(); for(int i=0; i<10; i++){ String seedPerson = allPerson.get(new Random().nextInt(allPerson.size())); if(i%2==0){ bGroup.add(seedPerson); }else{ aGroup.add(seedPerson); } allPerson.remove(seedPerson); } //A组名单 System.out.println("A组名单"); for(String aStr:aGroup){ System.out.println(aStr); } //B组名单 System.out.println("B组名单"); for(String bStr:bGroup){ System.out.println(bStr); }
大致意思是在将allPerson中的元素,随机分到aGroup 和bGroup 两个列表中去。核心的意思是每次从剩下的allPerson列表中随机取出(String seedPerson = allPerson.get(new Random().nextInt(allPerson.size()));
)一个员工,然后按照对2取模之后放到它应该的队列中去。
优化
看了这段代码以我对代码的审美标准,完全没有美感。于是很快的写了一段我认为美的代码:
List<String> allPerson = new ArrayList<String>(); allPerson.add("何XX"); allPerson.add("李XX"); allPerson.add("屈XX"); allPerson.add("刘XX"); allPerson.add("王XX"); allPerson.add("涂XX"); allPerson.add("张XX"); allPerson.add("方XX"); allPerson.add("何XX"); allPerson.add("周XX"); List<String> aGroup = new ArrayList<String>(); List<String> bGroup = new ArrayList<String>(); p = [aGroup ,bGroup ]; for(int i=0;i<allPerson.size();i++){ p[(int)(Math.random()*2)].add(list.get(i)); }
写完给我朋友看了一下,被他一语道破,最后得出的结果根本不符合他的需求,因为他要求的是两个列表结果集合是要相同的大小,我写的算法两个列表的大小是随机的,所以这个写法是错的。
被他指出之后,我重新想了一下该怎么写。应该先将列表随机排序一下,像这样的算法像我这样的懒人怎么会去开发呢,当然要依赖jdk中已经有的sdk工具。于是写了下面这段代码:
public void test() { List<String> allPerson = new ArrayList<String>(); allPerson.add("何XX"); allPerson.add("李XX"); allPerson.add("屈XX"); allPerson.add("刘XX"); allPerson.add("王XX"); allPerson.add("涂XX"); allPerson.add("张XX"); allPerson.add("方XX"); allPerson.add("何XX"); allPerson.add("周XX"); List<String> aGroup = new ArrayList<String>(); List<String> bGroup = new ArrayList<String>(); Collections.shuffle(allPerson); vist(allPerson.iterator(), aGroup, bGroup); System.out.println(aGroup); System.out.println(bGroup); } private void vist(Iterator<String> it, List<String> aGroup, List<String> bGroup) { if (!it.hasNext()) { return; } aGroup.add(it.next()); vist(it, bGroup, aGroup); }
这里利用了Collections.shuffle()这个函数先将allPerson 打散,然后用的迭代函数vist遍历allPerson,在每次迭代的时候将aGroup和bGroup参数位置互换一下,就能起到均匀给两个子列表添加记录了。当然这个遍历可以使用for循环用一个迭代子i++,每次判断取模之后是否为0,向两个子group中均匀添加数据。这种迭代的用法属于函数式编程的一个例子,每次看到迭代的方式实现一个函数,总感觉透着一股泥土般的清香,不是吗?