【问题标题】:random elements from a list DURING the addition添加期间列表中的随机元素
【发布时间】:2016-11-12 12:05:07
【问题描述】:

我的代码中有 20 个名字。 我的函数有 2 个选项可以将元素添加到我的列表中:

1.

将所有 20 个名称插入到列表中:

public void addNames() {
    list.add("name1");
    list.add("name2");
    ...
    list.add("name20");
}

2.

仅将 5 个随机名称(从 20 个名称中)添加到列表中。为此,我想到了两种方法。从 20 个名字中随机选择 5 个名字的最佳方法是什么?也许你有更好的方法。

答。

使用一组随机索引(每个值将在 0 到 19 之间,因为有 20 个名称),在“添加”之前,我将通过某个计数器检查是否添加它们:

public void addNames() {
    // adding 5 random indices between 0 to 19 to the set
    Set<Integer> set = new HashSet<Integer>();
    Random r = new Random();
    Set<Integer> indices = new HashSet<>(numRandomNames); //==5
    for (int i = 0; i < numRandomNames; ++i) {
        int index = r.nextInt(numNames - 0); //==19
        indices.add(index);
    }

    int counter = 0;
    if (indices.contains(counter)) {
        list.add("name1");
    }
    counter++;
    if (indices.contains(counter)) {
        list.add("name2");
    }
    counter++;
    if (indices.contains(counter)) {
        list.add("name3");
    }
    ...
}

B.

RandomList 扩展 List 并覆盖“add”函数以执行与“A.”相同的操作,但覆盖“add”将决定是否在函数内添加值,因此我的函数将看起来与 1. 相同,但带有 override 'add' 功能

您是否考虑过更好的解决方案?如果不是,那么哪个更好? (A 还是 B?)。我刚刚看到人们建议不要扩展 java 集合,但我认为这是这两个解决方案中最好的解决方案。

注意

====

我的代码甚至可以有 10000 个或更多名称,所以我不想将所有 10,000 个名称添加到 this\other 列表中,然后将其中的 5 个随机添加到其他列表中。我更喜欢在添加过程中这样做,以避免列表中的许多地方,而我并不真正需要它们。

编辑

对 ProgrammerTrond 的回答:

我不确定我是否会这样做,但我要求我展示的是我对 2.B 的建议:

public class RandomList<Integer> implements List<Integer> {
    private int addCallsCounter;
    private Set<Integer> setIndices = null;

    public RandomList(final int numElements, final int maxVal, final int minVal) {
        addCallsCounter = 0;
        setIndices =  new HashSet<Integer>(numElements);
        Random r = new Random();
        while (setIndices.size() < numElements) {
            int index = r.nextInt(maxVal - minVal + 1) + minVal;
            if (setIndices.contains(index) == false) {
                setIndices.add(index);
            }
        }
    }

    @Override
    public boolean add(Integer object) {
        if (setIndices.contains(addCallsCounter++)) {
            this.add(object);
            return true;
        }
        return false;
    }
}

从我的代码中我会这样做:

RandomList randList = new RandomList(5);
randList.add("name1");
randList.add("name2");
randList.add("name3");
...
randList.add("name19");
randList.add("name20");

但我的问题是我需要实现 List pfff 的许多抽象方法。 RandomList 也不能​​是抽象的,因为那样它就不能被实例化。

【问题讨论】:

  • 你的 10000 个名字存储在哪里?
  • 实际上并不是 10,000,但可以是 20-100。它们没有被存储,就像我展示的那样是硬编码的。
  • 它们是否存储在列表中?
  • 没有。它们根本没有存储,因为如果我只想在其余代码中随机使用 5 个它们,我认为这不是将它们全部存储在某个列表中的最佳方式
  • 如果您没有将它存储在任何地方,那么您将如何引用字符串。

标签: java android list arraylist random


【解决方案1】:

试试这个:

List<Integer> index = new ArrayList<>();
List<String> five_names = new ArrsyList<>();
List<String> allnames = new ArrayList<>();

存储五个随机值

for(int i = 0;i < 5;i++){

  int index_no = getrandomNumber();
  index.add(index_no);
  five_names.add(allnames.get(index_no));
}

getRandomNumber 方法:

public int getRandomNumber(){

    Random rnd = new Random();
    int x = rnd.nextInt(20);

    if(index.contains(x)){
       return getRandomNumber();
    }else{
       return x
    }
 }

【讨论】:

    【解决方案2】:

    为什么不喜欢这样?您不需要列表实现中的随机索引列表。您不只是想要一种方法,可以从一组可用名称中抽取 5 个随机名称添加到列表中吗?

    import java.util.*;
    public class ListAdding {
    
        private static List<String> allNames = Arrays.asList("name1", "name2", "name3", "name4", "name5", "name6", "name7");
    
        public static void main(String[] args) {
            new Temp().test();
        }
    
        void test() {
            List<String> list = new ArrayList<>();
            list.add("Bernie");
            addFiveRandom(list);
            for (int i = 0; i < list.size(); i++) {
                System.out.println(i + ": " + list.get(i));
            }
            // Example: 0: Bernie
            // 1: name2
            // 2: name3
            // 3: name6
            // and so on  
        }
    
        void addFiveRandom(List<String> toBeAddedTo) {
            List<Integer> indices = new ArrayList<>();
            while (indices.size() < 5) {
                int newIndex = new Random().nextInt(5);
                if (!indices.contains(newIndex))
                    indices.add(newIndex);
            }
            for (Integer index : indices) {
                toBeAddedTo.add(allNames.get(index));
            }
        }
    }
    

    【讨论】:

    • 我考虑过这个解决方案,但我认为最好避免使用包含所有元素的新列表,因为我只想在其余代码中使用其中的 5 个。我想到的解决方案是只使用 1 个列表,并自行决定是否实时添加值。
    • 如果您担心性能问题,可以在“add5Random”方法之外存储所有可用名称。我还想指出,当你只使用“nextInt(numNames - 0)”五次时,其中一些可能是重复的,然后你会得到少于 5 个随机名称。完成后你会考虑向我们展示你的代码吗?
    猜你喜欢
    • 2017-11-10
    • 1970-01-01
    • 2021-09-21
    • 1970-01-01
    • 1970-01-01
    • 2012-02-07
    • 2021-12-30
    • 1970-01-01
    • 2018-04-28
    相关资源
    最近更新 更多