我应该使用哪种Java集合类来完成这个任务?

13

我对Java还比较陌生,并且很难理解不同集合之间的区别。 我有一个包含19个资源的列表。每个资源都分配了一个十六进制颜色。 我想获取具有其颜色的随机资源,并将该资源与我的代码一起使用。 当我完成当前资源时,我想将其从列表中删除,以便仅使用一定数量的资源。

我应该使用字典,映射还是哈希表? 或者还有其他我没有考虑到的集合类型吗?


7
需要更多信息。您需要按某种方式对它们进行排序吗?资源是否可以添加多次?这些资源是否有某种可用于您搜索特定资源的标识符,还是您一次遍历所有资源并使用它们? - CodeMonkey
5
由于您只有19件物品,可以随心所欲地使用它们。您不会注意到任何变化。 - AdamSkywalker
5
ArrayList 能满足需求。Collections.shuffle() 会确保你得到的资源以随机顺序输出。 - Ole V.V.
1
好的,我开始想知道这19个资源到底是什么了...正如一个答案所指出的那样,它可能是一个包含颜色的类..但是,你提到了一个映射-键值关系.. - Bagus Tesa
2
@ShoeLace1291,你一开始写道:“我不认为我需要通过颜色来获取资源”,然后又写道:“我需要将颜色(值)分配给资源(键)”……那么到底是哪种情况呢? - CodeMonkey
显示剩余7条评论
4个回答

11
您可以将资源存储到List中,然后通过Collections.shuffle(List<?> list)shuffle(List<?> list, Random rnd)对其进行随机排列,并最终调用结果列表上的iterator()以获得Iterator实例,您可以将其存储到成员字段中,以便能够迭代您的列表(借助hasNext()/next())并在完成后使用remove()删除您的资源。

这里是一个伪代码示例,使用String作为资源,只是为了表达这个想法:

// Create a read/write list (Arrays.asList returns a read-only list)
List<String> resources = new ArrayList<>(Arrays.asList("1", "2", "3"));
System.out.printf("Initial state = %s%n", resources);
Collections.shuffle(resources);
System.out.printf("Permuted List = %s%n", resources);
Iterator<String> iterator = resources.iterator();
if (iterator.hasNext()) {
    String resource = iterator.next();
    // do something
    iterator.remove();
    System.out.printf("After remove = %s%n", resources);
}

输出:

Initial state = [1, 2, 3]
Permuted List = [3, 1, 2]
After remove = [1, 2]

NB:在您的情况下,这种方法是合理的,因为您有一个小列表,请注意,如果您有一个大列表并且只打算检索其中的一小部分,则应考虑使用Random随机获取下一个元素的索引(使用list.size()作为参数调用nextInt(int bound))进行获取(使用get(int index))和删除(使用remove(int index)),而不是使用Collections.shuffle(List<?> list),因为那会造成开销。


ArrayList无法工作,因为我需要将颜色(值)分配给资源(键)

如果您使用包含颜色和资源的包装类的List(例如AbstractMap.SimpleImmutableEntry或简单的自定义类),那么它可以工作。这足够好,因为您似乎不需要按资源检索颜色。如果您确实需要,您可以简单地拥有一个将资源作为键和颜色作为值的Map,并使用new ArrayList<>(map.keySet())初始化资源列表,然后您就能够应用此答案中之前提出的内容。


1
请注意,如果仅随机选择初始列表的一小部分元素,则对于大型列表,对整个列表进行洗牌会导致开销。 - SpaceTrucker
@SpaceTrucker 我同意,但这个列表只有 19 个元素,所以我不认为在这种情况下开销会很大,特别是如果只做一次,那么开销就会微不足道。 - Nicolas Filotto
请注意,new ArrayList 是必需的,因为从 Arrays.asList 返回的列表在尝试删除元素时会抛出 UnsupportedOperationException - JollyJoker
@JollyJoker 是的没错,Arrays.asList 返回一个只读列表。 - Nicolas Filotto
@NicolasFilotto,你说得对,这就是为什么我也点赞了你的回答。但由于这个问题已经得到了一些赞,更多的人可能会重复使用你的想法,我认为让他们意识到可能存在的额外开销是很好的。 - SpaceTrucker
@NicolasFilotto 这只是提供给其他读者的信息,显然你已经知道了。 - JollyJoker

3
如果您想根据其十六进制查找(获取)资源,请使用以下方法。
// Initialize
Map<String, Resource> resourceMap = new HashMap<>();
resourceMap.put("hex1", hex1Resource);
resourceMap.put("hex2", hex3Resource);
resourceMap.put("hex3", hex3Resource);

// Get specific
Resource hex2Resource = resourceMap.get("hex2");
resourceMap.remove("hex2");

如果您想要随机查找资源,有两个选项:

  • 使用列表(允许重复值)
  • 使用集合(仅存储唯一值)

使用列表

// Initialize
List<Resource> list = new ArrayList<>();
list.add(resource1);
list.add(resource2);
list.add(resource3);

// Get random
Random rand = new Random();
Resource randomResource = list.get(rand.nextInt(list.size()));

// Delete the element from list
list.remove(randomResource);

使用集合
// Initialize
Set<Resource> set = new HashSet<>();
set.add(resource1);
set.add(resource2);
set.add(resource3);

// Convert to List, since Set does not have get(int) method. 
List<Resource> list = new ArrayList<>(set);

// Get random
Random rand = new Random();
Resource randomResource = list.get(rand.nextInt(list.size()));

// Delete the element from list
list.remove(randomResource);

注意:对于上述两种情况,Resource类都需要实现equals和hashcode方法,以便列表/集合可以比较元素并正常工作。请参见Java equals and hashcode 更新:集合没有get(int)方法。已更新代码以修复此问题。

1
@sameerasy 总是有 List<Map.Entry<Color,Resource>> 的选项,或者为数据创建一个自定义的包装类。 - 4castle
@gtiwari333 一个List可以允许重复。 - 4castle
@4castle,我在谈论Map.Entry<Color,Resource>。 - gtiwari333
这里假设 Resource 类具有颜色属性(字符串),并且 equals 和 hashcode 基于该属性。 - DeepakV
@4castle,你是对的。我最初把List<Map.Entry>当作List<Map> :) - gtiwari333
显示剩余8条评论

0

以下代码应该可以正常工作。步骤如下:

  1. 创建一个资源列表
  2. 生成一个随机数并获取该项
  3. 对您的随机项执行所需操作
  4. 从列表中删除它

示例代码:

 //1
List<Resource> resources= getList();

//2
Random generator = new Random();
Resource randomResource = resources.get(generator.nextInt(resources.size() -1));

//3
//do your stuff

//4
resources.remove(randomResource);

资源可以是一个包装您数据的类

class Resource{
    String color;
    String otherProperties;
    //..


    @Override
    public boolean equals(Object obj) {
        //generate from IDE or write one
    }

    @Override
    public int hashCode() {
        //generate from IDE or write one
    }
}

0

引用

如果你需要随机顺序,最好使用List对象。

List<String> resourceMap = new CopyOnWriteArrayList<>();
          resourceMap.add("hex1");
          resourceMap.add("hex2");
          resourceMap.add("hex3");
          resourceMap.add("hex4");
          Collections.shuffle(resourceMap);
          resourceMap.forEach(resource->{
              resourceMap.remove(resource);
          });

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