Java:获取ArrayList的随机不连续子列表(最有效的方法)

7
简单地说,我的问题是:如何以最有效的方式检索给定大小的 ArrayList 的随机不连续子列表。
以下是我自己设计的代码,它可以工作,但对我来说似乎有点笨重。顺便说一下,这是我的第一个 JAVA 程序,请原谅如果我的代码或问题不符合最佳实践 ;)
注: - 我的列表不包含重复项 - 如果目标大小大于原始列表的一半,则我“猜测”删除项目可能比添加项目更快
public ArrayList<Vokabel> subList(int AimSize) {
    ArrayList<Vokabel> tempL = new ArrayList<Vokabel>();
    Random r = new Random();
    LinkedHashSet<Vokabel> tempS = new LinkedHashSet<Vokabel>();

    tempL = originalList;

    // If the size is to big just leave the list and change size 
    // (in the real code there is no pass-by-value problem ;)
    if (!(tempL.size() > AimSize)) {
        AimSize = tempL.size();
    // set to avoid duplicates and get a random order
    } else if (2* AimSize < tempL.size()) {
        while (tempS.size() < AimSize) {
            tempS.add(tempL.get(r.nextInt(tempL.size())));
        }
        tempL = new ArrayList<Vokabel>(tempS);
    // little optimization if it involves less loops
    // to delete entries to get to the right size, than to add them
    // the List->Set->List conversion at the end is there to reorder the items
    } else {
        while (tempL.size() > AimSize) {
            tempL.remove(r.nextInt(tempL.size()));
        }
        tempL = new ArrayList<Vokabel>(new LinkedHashSet<Vokabel>(tempL));

    }

    return tempL;
}

首先,List 中有一个 subList 方法。 - johnchen902
还有 java.util.Collections.shuffle(java.util.List) - johnchen902
@johnchen902 我之前不知道shuffle这个方法。如果我先对列表进行shuffle,然后再使用subList方法,应该就可以解决问题了。 - Sergej
我最初认为你需要一个连续的子列表。在这种情况下,使用subList和一个随机起点... - johnchen902
2个回答

17

警告:这段代码是在我的浏览器中编写的,甚至可能无法编译!

使用Collections.shuffleList.subList可以完成该任务。

public static <T> List<T> randomSubList(List<T> list, int newSize) {
    list = new ArrayList<>(list);
    Collections.shuffle(list);
    return list.subList(0, newSize);
}

即使效率放在一边(这里肯定会更好),任何使用3行而不是30行的代码都会受到高度赞赏。 谢谢! - Sergej
干得好,谢谢。 - Dariop

1

另一种使用Java 8流的解决方案是这样的

 public static <T> List<T> selectRandomElements(List<T> list, int amount) {
        if( amount > list.size())
            throw new IllegalArgumentException("amount can't be bigger than list size");

        return Stream.generate( () -> list.get( (int) ( Math.random() * list.size() ) ) )
            .distinct()
            .limit( amount )
            .collect( Collectors.toList() );
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接