Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java中的java.util.Random和递归_Java_Recursion - Fatal编程技术网

java中的java.util.Random和递归

java中的java.util.Random和递归,java,recursion,Java,Recursion,首先,我想说这是一个更一般的问题;不是关于我给出的具体例子,而是一个概念性的主题 例1: 我正在用UUID.java创建一个真正的随机字符串。比方说,我永远不想生成相同的UUID,永远不。这里有一个关于情况的想法: 让我们假设我正在顶部保存/加载列表-这不是重点 例2:好吧,也许UUID是个坏例子,所以让我们使用Random和double。下面是另一个例子: 要点:这是做这种事情最有效的方法吗?记住我给过你一些例子,所以它们都很模糊。我更愿意不使用任何库来实现这一点,但如果它们在效率上确实存在重

首先,我想说这是一个更一般的问题;不是关于我给出的具体例子,而是一个概念性的主题

例1: 我正在用UUID.java创建一个真正的随机字符串。比方说,我永远不想生成相同的UUID,永远不。这里有一个关于情况的想法: 让我们假设我正在顶部保存/加载列表-这不是重点

例2:好吧,也许UUID是个坏例子,所以让我们使用Random和double。下面是另一个例子:

要点:这是做这种事情最有效的方法吗?记住我给过你一些例子,所以它们都很模糊。我更愿意不使用任何库来实现这一点,但如果它们在效率上确实存在重大差异,请让我知道它们


请让我知道您在回复中的想法:

使用哈希表比列表更好。生成候选值,检查哈希表中是否存在冲突,如果没有冲突,则接受该值。如果使用列表,则生成新值是一个On操作。如果使用哈希表,则生成新值是一个O1操作。

使用哈希表比使用列表更好。生成候选值,检查哈希表中是否存在冲突,如果没有冲突,则接受该值。如果使用列表,则生成新值是一个On操作。如果使用哈希表,则生成新值是一个O1操作。

我建议您将生成的ID按顺序编号,而不是双精度或UUID。如果希望最终用户将其随机显示,请在base64中显示数字的sha1。

我建议您将生成的ID序列号改为双倍或UUID。如果希望最终用户将其随机显示,请在base64中显示数字的sha1。

注释中已经讨论了一些要点。在此总结和阐述:

不太可能两次创建相同的双精度值。假设随机数生成器可以提供其中的大部分。对于UUID,创建相同值两次的机会更低,因为。如果您创建了足够多的元素,从而有不可忽略的碰撞机会,那么无论如何都会耗尽内存

因此,这种方法在实践中没有意义

然而,从纯理论的角度来看:

表演 为此操作使用列表不是最佳选择。对于您来说,最好的情况也是最常见的情况是列表中不包含新元素。但是对于检查元素是否包含,这是最坏的情况:您必须检查列表中的每个元素,只检测到新元素尚未出现。这被称为是线性的,或者简而言之,是线性的。您可以使用另一种数据结构,即在O1中,可以更快地检查元素是否包含。例如,您可以替换该行

private static final List<Double> PREVIOUS = new ArrayList<Double>();

性能和正确性 这里一般指的是递归方法

演出

从性能的角度来看,当递归很容易被迭代解决方案取代时,不应该使用递归。在这种情况下,这将是微不足道的:

public static double generateUniqueDouble(List<Double> previous) {
    double d = RANDOM.nextDouble();
    while (previous.contains(d)) {
        d = RANDOM.nextDouble();
    }
    PREVIOUS.add(d);
    return d;
}
它可以写得更紧凑一点,但现在这并不重要

正确性

这是更微妙的:当有许多递归调用时,您可能最终得到一个StackOverflowerError。因此,除非您能够证明递归将结束或更好:它将在几个步骤后结束,否则您永远不应该使用递归

但你的主要问题是:

算法有缺陷。你无法证明它能够创建一个新的随机数。对于double或UUID值,即使单个新元素已经包含在先前元素的集合中的可能性也低得离谱。但它不是零。没有任何东西可以阻止随机数生成器无限期地创建0.5的随机数,连续数万亿次


再说一遍:这些纯粹是理论上的考虑。但与他们第一眼看到的实际情况相差不远:如果您没有创建随机双精度值,而是创建随机字节值,那么,在256次调用之后,将不会返回新值-并且您将实际收到StackOverflowerr…

注释中已经讨论了一些要点。在此总结和阐述:

不太可能两次创建相同的双精度值。假设随机数生成器可以提供其中的大部分。对于UUID,创建相同值两次的机会更低,因为。如果您创建了足够多的元素,从而有不可忽略的碰撞机会,那么无论如何都会耗尽内存

因此,这种方法在实践中没有意义

然而,从纯理论的角度来看:

表演 使用Lis 对于这个操作,t不是最优的。对于您来说,最好的情况也是最常见的情况是列表中不包含新元素。但是对于检查元素是否包含,这是最坏的情况:您必须检查列表中的每个元素,只检测到新元素尚未出现。这被称为是线性的,或者简而言之,是线性的。您可以使用另一种数据结构,即在O1中,可以更快地检查元素是否包含。例如,您可以替换该行

private static final List<Double> PREVIOUS = new ArrayList<Double>();

性能和正确性 这里一般指的是递归方法

演出

从性能的角度来看,当递归很容易被迭代解决方案取代时,不应该使用递归。在这种情况下,这将是微不足道的:

public static double generateUniqueDouble(List<Double> previous) {
    double d = RANDOM.nextDouble();
    while (previous.contains(d)) {
        d = RANDOM.nextDouble();
    }
    PREVIOUS.add(d);
    return d;
}
它可以写得更紧凑一点,但现在这并不重要

正确性

这是更微妙的:当有许多递归调用时,您可能最终得到一个StackOverflowerError。因此,除非您能够证明递归将结束或更好:它将在几个步骤后结束,否则您永远不应该使用递归

但你的主要问题是:

算法有缺陷。你无法证明它能够创建一个新的随机数。对于double或UUID值,即使单个新元素已经包含在先前元素的集合中的可能性也低得离谱。但它不是零。没有任何东西可以阻止随机数生成器无限期地创建0.5的随机数,连续数万亿次



再说一遍:这些纯粹是理论上的考虑。但与他们第一眼看到的实践相差不远:如果您没有创建随机双精度值,而是创建随机字节值,那么,在256次调用之后,将不会有新的值返回-并且您将实际收到StackOverflower错误…

您将生成多少内容?@Aify我很可能会实际生成很多内容。@Aify很抱歉回答含糊不清,没有意识到enter已发送。我使用它来生成用户从指定服务器下载包时的一次性密钥。首先想到的问题是,由于您将所有内容都存储在列表中,所以最终会耗尽内存-特别是如果您要生成一个列表,如果生成了很多这样的密钥,它们决不能冲突,为什么不让它们按顺序排列?您将生成多少内容?@Aify我很可能会生成很多内容。@Aify很抱歉回答含糊不清,没有意识到enter是发送的。我使用它来生成用户从指定服务器下载包时的一次性密钥。首先想到的问题是,由于您将所有内容都存储在列表中,所以最终会耗尽内存-特别是如果您要生成一个列表,如果生成了很多这样的密钥,它们决不能冲突,为什么不让它们按顺序排列呢?嗯,我肯定会详细研究一下哈希表。然而,当你说如果没有碰撞就接受它时,如果是碰撞怎么办?我是否应该像在示例中那样使用递归?如果发生冲突,则生成一个新的随机值并重试。使用循环执行此操作将比递归更有效,但老实说,如果使用计时,我怀疑您是否会看到差异。嗯,我肯定会更多地研究哈希表。然而,当你说如果没有碰撞就接受它时,如果是碰撞怎么办?我是否应该像在示例中那样使用递归?如果发生冲突,则生成一个新的随机值并重试。使用循环比递归更有效,但老实说,如果使用计时,我怀疑您是否会看到差异。感谢您的回答,这很可能是我将使用的,而不仅仅是显示序列号。只是一个小问题-在您解释的方法中,询问显示数字的最有效方法是否不合主题?或者,我应该做更多的研究并提出另一个问题吗?那是另一个问题。有后续问题是可以的,但如果是不同的问题,可以单独发布。这是个好主意。不确定是否符合要求;这取决于未来价值的猜测是否重要。我不得不将推荐答案改为Marco13的答案,不是因为我不喜欢你的答案,而是因为他提供了很多例子,谢谢你的帮助!我会支持你的答案,但我是新来的,没有足够的信誉点,对不起!谢谢你的回答,这很可能是我将要使用的,而不仅仅是显示序列号。只是一个小问题-在您解释的方法中,询问显示数字的最有效方法是否不合主题?或者,我应该做更多的研究并提出另一个问题吗?那是另一个问题。很好
有后续问题,但如果是不同的问题,可以单独发布。这是个好主意。不确定是否符合要求;这取决于未来价值的猜测是否重要。我不得不将推荐答案改为Marco13的答案,不是因为我不喜欢你的答案,而是因为他提供了很多例子,谢谢你的帮助!我会支持你的答案,但我是新来的,没有足够的信誉点,对不起!谢谢你的非常详细的评论,帮助了我很多,我相信它会帮助别人!我真不敢相信我忘了一会儿。然而,我有一个小问题。这一行:当条件为真时,虽然previous.containsd显然正在运行循环,但是,我们不需要相反的条件吗!上一篇文章是什么?不管怎样,再次感谢你宽泛的回答,我将修改我的策略:也许我正在锁定咖啡,但我认为虽然previous.containsd应该是正确的:只要生成的号码包含在集合中,就应该创建一个新号码。啊,我的坏朋友,请重读它。昨晚我真的很累,我很抱歉谢谢你的详细评论,帮了我很多,我相信这会对其他人有帮助!我真不敢相信我忘了一会儿。然而,我有一个小问题。这一行:当条件为真时,虽然previous.containsd显然正在运行循环,但是,我们不需要相反的条件吗!上一篇文章是什么?不管怎样,再次感谢你宽泛的回答,我将修改我的策略:也许我正在锁定咖啡,但我认为虽然previous.containsd应该是正确的:只要生成的号码包含在集合中,就应该创建一个新号码。啊,我的坏朋友,请重读它。对不起,我昨晚真的很累
public static double generateUniqueDouble(List<Double> previous) {
    double d = RANDOM.nextDouble();
    while (previous.contains(d)) {
        d = RANDOM.nextDouble();
    }
    PREVIOUS.add(d);
    return d;
}