一个小问题引发的思考

随机生成20个不重复A-Z的字符串,并且顺序排列

题目挺简单要注意几个点,一 :A-Z的生成 二 : 随机数 三  :不重复,  顺序排列

A-Z的生成:利用ascii码表生成字母  //确定A-Z的   ascii码表   (65-90)

i=65char c=(char) i;//c即为"A"

再利用随机数生成 不同的字符串

 int i=new Random().nextInt(26)+65;

20个不重复的,循环确定个数,set保存不重复的对象集合

	while(true){
	    int i=new Random().nextInt(26)+65;
	       char c=(char) i;
	       if(set.size()<=20){
	    	   set.add(c);
	       }
	       else{
	    	   break;
	       }
		}

 最后一步:顺序保存,只需要set集合使用treeSet就可,treeSet是根据对象实现comparable接口按顺序保存对象。

完整例子

public static void main(String[] args) {
        //确定A-Z的   ascii码表   (65-90)
        TreeSet<Character> set =new TreeSet<Character>();
        while(true){
        int i=new Random().nextInt(26)+65;
           char c=(char) i;
           if(set.size()<=20){
               set.add(c);
           }
           else{
               break;
           }
        }

        for(Iterator<Character> i=set.iterator();i.hasNext();){
              char c=  i.next();
              System.out.println(c);
        }
    }

上述只是一个很简单的小问题,但有两个问题可以深入探讨下

一:随机数 

java生成的随机数是伪随机数,即不是真正的随机,只是按照一定的规则模拟出来的。

java中生成随机数有两种方法   一种就是开始上面实现的随机数    int i=new Random().nextInt(26) 生成一个0-25的实际整数

另一种则是  Math.random()    生成一个0-1的浮点数

这两种的区别

先看  Math.random() 的源码

 private static Random randomNumberGenerator;

    private static synchronized Random initRNG() {
        Random rnd = randomNumberGenerator;
        return (rnd == null) ? (randomNumberGenerator = new Random()) : rnd;
    }

  public static double random() {
        Random rnd = randomNumberGenerator;
        if (rnd == null) rnd = initRNG();
        return rnd.nextDouble();
    }

简单的说,Math.random() 还是调用了 random对象的 nextDouble()方法,只不过random对象是静态的,单一的,上锁的random对象

接下来看  nextDouble()方法,nextDouble()调用了next()方法,值得说下的是,nextInt()方法之调用了一次next(),速度会比nextDouble()快一丢丢

 public double nextDouble() {
        return (((long)(next(26)) << 27) + next(27))
            / (double)(1L << 53);
    }

接下来继续看next()方法, next()中有一个很重要的属性  oldseed,所有运算结果都是根据它生成,而oldseed是怎么生成的

 protected int next(int bits) {
        long oldseed, nextseed;
        AtomicLong seed = this.seed;
        do {
            oldseed = seed.get();
            nextseed = (oldseed * multiplier + addend) & mask;
        } while (!seed.compareAndSet(oldseed, nextseed));
        return (int)(nextseed >>> (48 - bits));
    }

又下面可以知道.oldseed是由几个常数 加系统时间来运算确定的 ,所以呢java随机数不是真随机只是个伪随机,并且不是很安全,因为很容易被算是随机值,但是可以用java.security.SecureRandom,这个更安全,因为重写了next()方法。

 public Random() {
        this(seedUniquifier() ^ System.nanoTime());
    }

    private static long seedUniquifier() {
        // L‘Ecuyer, "Tables of Linear Congruential Generators of
        // Different Sizes and Good Lattice Structure", 1999
        for (;;) {
            long current = seedUniquifier.get();
            long next = current * 181783497276652981L;
            if (seedUniquifier.compareAndSet(current, next))
                return next;
        }
    }

    private static final AtomicLong seedUniquifier
        = new AtomicLong(8682522807148012L);

最后:http://blog.csdn.net/ultrani/article/details/7818082 这边博文的作者写的更清晰,也更深入的说明random函数算法的原理,有兴趣可以去看下

时间: 2024-10-05 23:37:57

一个小问题引发的思考的相关文章

由一个投票算法引发的思考

博主的APP最近又新加了一个小功能,每个员工都可以上传自己的工作照,其他员工可以点赞,规则是:每张工作照每个员工(除上传者外)每日可点赞一次.举个例子: 现有注册员工ABCD四人,A上传工作照两张P1和P2,BCD三人每天可为P1.P2分别点赞一次 博主略加思考,写了下面一段代码来实现: 1 /// <summary> 2 /// 投票 3 /// </summary> 4 /// <param name="id">被投票对象ID</param

一个小错误引发思考最终得出数组转字符串的新方法

今天在项目中犯了一个算得上是低级错误的错误吧 我在构造函数里声明了一个angle变量, this.angle; 然后在后面某函数中对此变量进行了+=操作, this.angle+=90 最后在一系列逻辑后我发现this.angle报错 NaN,马上定位到构造函数,就发现了原来该变量声明了但并未初始化赋值 求不笑,偶尔也是会傻乎乎犯些这种低级错误的,而这一次暴露出来完全是因为我在后面使用了+=操作,如果后面是单纯的 = 赋值操作,这样构造函数里是可以不初始化的 这时,我突然想试试如果+=后面不是数

由项目中一个hash2int函数引发的思考

hash2int /** * 计算一个字符串的md5折算成int返回 * @param type $str * @return type */ function hash2int($str) { $md5str = md5($str, true); $one = unpack('l', substr($md5str, 0, 4)); $two = unpack('l', substr($md5str, 4, 4)); $three = unpack('l', substr($md5str, 8,

MVC系列——一个异常消息传递引发的思考

前言:最近在某个项目里面遇到一个有点纠结的小问题,经过半天时间的思索和尝试,问题得到解决.在此记录一下解决的过程,以及解决问题的过程中对.net里面MVC异常处理的思考.都是些老生常谈的问题,不多说,直接上“主菜”. 本文原创地址:http://www.cnblogs.com/landeanfen/p/8135844.html 一.问题重现 项目是一个传统.net framework的MVC项目,为了简便,项目里面定义了一个自定义异常类用于向客户端传递错误消息,客户端接收到异常的消息时在浏览器里

前后端交互模型(一个面试题引发的思考总结)

客户端和服务端的交互 面试题: 当用户在地址栏中输入网址,到最后看到页面,中间都经历了什么? (引出前后端交互模型的内容) 客户端 =======> 服务端 (request请求阶段) 服务端 <======= 客户端 (responese响应阶段) 1.URL地址解析 2.DNS域名解析(DNS服务器) 3.和服务器建立TCP连接 (三次握手) 4.把客户端信息传递给服务器(发送HTTP请求) 5.服务器得到并处理请求(HTTP响应内容) 6.客户端渲染服务器返回的内容 7.和服务器端断开T

由一个DAOHelper类引发的思考

这是一篇发牢骚的文章,可以这么说吧.DAOHelper究竟有什么用呢?用我自己的话去理解,DAOHelper的存在正是敏捷开发的产物,即快速开发. 我们究竟能从项目中学到什么呢?有的人可能会说,从一个项目中,你可以学到很多东西,比如你可以学习Nhibinate,Entity Framework 等ORM框架,还可以学习到LINQ 2 SQL等技术,但是,一个DAOHelper就能毁掉你的梦想.我们不妨来看看下面的一些代码. using System; using System.Collectio

由一个emoji引发的思考

由一个emoji引发的思考 从毕业以来,基本就一直在做移动端,但是一直就关于移动端的开发,各种适配问题的解决,在日常搬砖中处理了就过了,也没有把东西都沉淀下来,觉得甚是寒颜.现就一个小bug,让我们来了解一下我们天天都在用的emoji,对于开发来说,是一个怎么样的存在. 背景 之前在做一个留言功能时,发现在其中一台安卓5.0的手机上,输入emoji糊掉了,成了如下这样的情况 这是skr啥玩意儿呀,怎么看上去像某白色幼虫. 与是我又试了好几个手机,ios都没有问题,甚至一台安卓机中之霸(安卓4.0

一个回车符引发的问题思考

在维护和开发通信类软件产品的过程中,经常需要处理一些软件故障问题.在问题刚出现的时候,大家可能显得手足无措,有一种天都要塌下来的感觉.但在问题原因找到之后,大家又会觉得问题原因非常的简单,要是当初开发的时候仔细一点,是不会犯这样的低级错误的.最近,本人就遇到了一个回车符引发的问题. 近日,在开发某软件版本时需要对文件进行操作,在代码中使用了Linux C语言中的opendir函数,但是该函数始终返回NULL,提示文件路径不存在. 本人查了一下该函数的具体情况.opendir函数的原型为: DIR

一个截取字符串函数引发的思考

背景 前些天,遇到这样一个问题,问题的内容如下: 要求编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串.但是要保证汉字不被截半个,如"我ABC", 4,截取后的效果应该为"我AB",输入"我ABC汉DEF", 6,应该输出为"我ABC",而不是"我ABC+汉的半个". 问题 刚看到这个问题的时候,以为还是很简单的,但写出来之后,发现并不是想要的效果.回想一下当时的思路,就发现刚开