为什么Set不提供获取等于另一个元素的元素的操作?我没有得到那个元素吗? :(

为了澄清起见,Set方法被覆盖,但它仅检查一个字段,而不是全部。因此,两个被认为相等的bar对象实际上可以具有不同的值,这就是为什么我可以做到这一点只需使用equals

评论

这篇文章已经被广泛讨论,并提出了很好的答案。但是,如果您只是在寻找有序集合,只需使用SortedSet及其基于地图的实现(例如TreeSet允许访问first())。

对于上面描述的完全相同的情况,我也缺少该方法。 Objective-C(NSSet)具有这种方法。它称为成员,它返回集合中的对象,该对象将“等于”与成员方法的参数进行比较(当然,它可能是一个不同的对象,并且也具有不同的属性,该相等可能不会检查)。

#1 楼

如果元素相等,将毫无意义。一个Map更适合此用例。 br />

评论


绝对有可能获得该元素。如果您希望在元素已添加到Set中之后更新某些元素的值该怎么办?例如,当.equals()未使用所有字段时,如指定的OP。效率较低的解决方案是删除元素,然后将其值更新后重新添加。

–凯尔
13年2月19日在17:48

我仍然会认为Map更适合(在这种情况下,Map 。)

– dacwe
13年2月19日在20:48

@dacwe,我到达这里是因为我开始寻找一种避免这种情况的方法!同时充当键和相应值的对象正是集合的全部含义。就我而言,我想通过键(字符串)从集合中获取一些复杂的对象。此String被封装(并且是唯一的)到要映射的对象。实际上,整个对象围绕所述键“旋转”。而且,调用者知道所说的字符串,但不知道对象本身。这就是为什么它要通过键检索它的原因。我现在正在使用地图,但是它仍然是奇怪的行为。

–pauluss86
2014年1月16日19:29

@KyleM我了解用例,但是我想强调不要触摸hashCode / equals的属性的重要性。来自Set Javadoc:“注意:如果将可变对象用作set元素,则必须格外小心。如果对象的值以影响equals比较的方式更改,而对象是集合中的元素。” -我建议这些对象是不可变的,或者至少具有不可变的键属性。

– stivlo
15年2月26日在17:33

我同意您可以使用Map 来代替,缺点是地图始终必须至少存储一个键和一个值(为了性能,它还应该存储散列),而集合可以散开只是存储值(可能为性能而散列)。因此,一个好的set实现对于Map 可以同样快,但占用的内存最多减少50%。在Java的情况下,这无关紧要,因为HashSet始终在内部基于HashMap。

–梅基
15年3月6日在17:38

#2 楼

为了回答精确的问题“为什么Set不提供获取等于另一个元素的元素的操作?”,答案将是:因为集合框架的设计者并不十分前瞻。他们没有想到您的使用案例非常合法,只是天真地尝试“对数学集抽象进行建模”(来自javadoc),而只是忘记添加有用的get()方法。那么如何获得元素”:我认为最好的解决方案是使用Map<E,E>而不是Set<E>来将元素映射到自身。这样,您可以有效地从“集合”中检索元素,因为Map的get()方法将使用高效的哈希表或树算法来找到该元素。如果需要,您可以编写自己的Set实现,该实现提供附加的get()方法,将Map封装起来。

以下答案在我看来是好是坏: “您不需要获取元素,因为您已经有一个相等的对象”:断言是错误的,正如您在问题中已经表明的那样。相等的两个对象仍然可以具有与对象相等无关的不同状态。目的是访问Set中包含的元素的此状态,而不是用作“查询”的对象的状态。

“您别无选择,只能使用迭代器” :这是对集合的线性搜索,对于大型集合而言这是完全无效的(具有讽刺意味的是,内部Set被组织为可以有效查询的哈希图或树)。别做!通过使用该方法,我已经看到了现实系统中的严重性能问题。在我看来,缺少get()方法的可怕之处并不在于解决它有点麻烦,而是大多数程序员会在不考虑其含义的情况下使用线性搜索方法。

评论


嗯此处,问题在于重写等于的实现,以使非等于的对象成为“等于”。要求提供一种方法,说“给我与该对象相同的对象”,然后期望返回一个不相同的对象,这似乎很疯狂,很容易引起维护问题。正如其他人所建议的那样,使用地图可以解决所有这些问题:它使您所做的事情不言自明。很容易理解,两个不相等的对象在映射中可能具有相同的键,而具有相同的键将显示它们之间的关系。

–大卫·奥格伦(David Ogren)
2014-02-10 22:27



强有力的话,@ David Ogren。嗯疯?但是在您的评论中,您使用的是“相同”和“相等”,就好像它们是同一意思。他们不。具体来说,在Java中,标识由“ ==”运算符表示,而相等由equals()方法表示。如果它们的意思相同,则根本不需要equals()方法。用其他语言,这当然可以不同。例如,在Groovy中,标识是is()方法,相等性是“ ==”。好笑,不是吗?

– jschreiner
2014-2-27 14:11



当我应该使用等效这个词时,您对我使用相同这个词的批评是非常有效的。但是,在对象上定义均等以使Foo和Bar“等于”但不足以让他等效地使用它们,这将在功能和可读性/可维护性方面造成各种问题。 Set的这个问题只是潜在问题的冰山一角。例如,相等的对象必须具有相等的哈希码。因此,他将有潜在的哈希冲突。对象专门调用.get(foo)以获取foo以外的内容是否疯狂?

–大卫·奥格伦(David Ogren)
2014年2月27日14:47

可能值得注意的是,例如HashSet被实现为HashMap的包装器(将键映射到虚拟值)。因此,显式使用HashMap代替HashSet不会导致内存使用方面的开销。

– Alexey B.
2014年6月19日在23:20



@ user686249我觉得这已经演变成一场学术辩论。我确实承认,我可能在反对压倒一切方面有些落伍。特别是在像您这样的用途中。但是,我仍然反对调用此方法get()的想法。在您的示例中,customerSet.get(thisCustomer)会让我非常困惑。 (鉴于许多答案都建议使用地图,那么使用canonicalCustomerMap.get(此客户)就可以了。我也可以使用更明确命名的方法(例如NSSet上的Objective-C的成员方法)。

–大卫·奥格伦(David Ogren)
2015年4月30日在13:34



#3 楼

如果您有一个相等的对象,那么为什么需要集合中的那个?如果仅通过键“相等”,则Map将是一个更好的选择。无论如何,以下方法可以做到: />使用Java 8,它可以变成一个衬里:

Foo getEqual(Foo sample, Set<Foo> all) {
  for (Foo one : all) {
    if (one.equals(sample)) {
      return one;
    }
  } 
  return null;
}


评论


我更喜欢这个答案,我只会避免使用两个return语句,因为这是针对OOP的,这会使Cyclomatic Complexity值更高。

–狮子座
16 Dec 16'在18:21

@Leo谢谢,但是单出口范例并不反对OOP,并且对于比Fortran或COBOL更现代的语言而言,大多数情况下是无效的,另请参见softwareengineering.stackexchange.com/questions/118703/…

– Arne Burmeister
16 Dec 17'0:39

使用Map而不是Set似乎是一个更好的选择:遍历Set的元素比从Map中获取单个值要花更多的工作。 (O(N)与O(1))

–杰米·弗洛诺(Jamie Flournoy)
18-10-5在21:16

@JamieFlournoy,如果您必须多次检查同一集合中的不同元素,那就更好了。无需一次性使用,因为首先需要花费更多的精力来构建地图。

– Arne Burmeister
18-10-5在21:20

#4 楼

不幸的是,正如jschreiner正确解释的那样,Java中的Default Set并非旨在提供“获取”操作。

使用迭代器查找感兴趣元素(由dacwe建议)或删除元素并重新添加其元素,并使用更新的值(由KyleM建议),虽然可以,但是效率非常低。正如David Ogren正确指出的那样,很容易导致维护问题。

imho使用Map作为显式替换(很多人建议),恕我直言,使代码不太优雅。

如果目标是访问集合中包含的元素的原始实例(希望我能正确理解您的用例),那么这是另一种可能的解决方案。


I使用Java开发客户端-服务器视频游戏时,个人有相同的需求。以我为例,每个客户端都有存储在服务器中的组件的副本,问题出在每当客户端需要修改服务器对象时。

通过互联网传递对象意味着客户端已经无论如何,该对象的不同实例。为了使此“复制”实例与原始实例匹配,我决定使用Java UUID。 。

此UUID在客户端和服务器实例之间共享,因此通过这种方式,只需使用Map即可轻松匹配它们。

直接使用Map在类似的用例中仍然不雅。有人可能会争辩说,使用Map进行维护和处理可能会更加复杂。

由于这些原因,我实现了一个名为MagicSet的库,该库使开发人员对Map的使用“透明”。 />
https://github.com/ricpacca/magicset


像原始的Java HashSet一样,MagicHashSet(库中提供的MagicSet的实现之一)使用支持HashMap,但不是将元素作为键并将伪值作为值,而是使用元素的UUID作为键。元素本身就是价值。与普通的HashSet相比,这不会导致内存使用方面的开销。

此外,MagicSet可以与Set完全一样使用,但是还有更多提供其他功能的方法,例如getFromId(),popFromId(),removeFromId()等。

使用它的唯一要求是,要存储在MagicSet中的任何元素都需要扩展抽象类UniqueItem。


这里是一个代码示例,试图检索该对象。 MagicSet中某个城市的原始实例,并给出该城市的另一个实例,该实例具有相同的UUID(甚至只是其UUID)。

class City extends UniqueItem {

    // Somewhere in this class

    public void doSomething() {
        // Whatever
    }
}

public class GameMap {
    private MagicSet<City> cities;

    public GameMap(Collection<City> cities) {
        cities = new MagicHashSet<>(cities);
    }

    /*
     * cityId is the UUID of the city you want to retrieve.
     * If you have a copied instance of that city, you can simply 
     * call copiedCity.getId() and pass the return value to this method.
     */
    public void doSomethingInCity(UUID cityId) {
        City city = cities.getFromId(cityId);
        city.doSomething();
    }

    // Other methods can be called on a MagicSet too
}


#5 楼

将集转换为列表,然后使用列表的get方法

Set<Foo> set = ...;
List<Foo> list = new ArrayList<Foo>(set);
Foo obj = list.get(0);


评论


我不明白这将检索集合中的任意对象。不是对象。

– aioobe
17年8月19日在22:39

为什么会有这么多的投票?在此答案中,您将集合转换为列表并检索了第一个对象,而不是“ foo”

– Uri Loya
7月20日11:27



使其过于复杂,并使其效率非常低(消耗大量内存,速度很慢)。正确的方法是使用地图。

– zakmck
10月5日下午16:34

#6 楼

如果您的集合实际上是NavigableSet<Foo>(例如TreeSet)和Foo implements Comparable<Foo>,则可以使用

Foo bar = set.floor(foo); // or .ceiling
if (foo.equals(bar)) {
    // use bar…
}

(感谢@ eliran-malka的注释。 )

评论


如果我不介意任何人阅读我的代码时,最初以为我完全疯了,那将是一个不错的解决方案。

–亚当
17年11月9日17:47

#7 楼

使用Java 8,您可以执行以下操作:

Foo foo = set.stream().filter(item->item.equals(theItemYouAreLookingFor)).findFirst().get();


但是要小心,.get()会引发NoSuchElementException,或者您可以操纵Optional项。

评论


item-> item.equals(theItemYouAreLookingFor)可以简化为ItemYouAreLookingFor :: equals

– Henno Vermeulen
18年5月3日在6:40

#8 楼

原因:

Set似乎在提供比较手段方面发挥了有用的作用。它被设计为不存储重复的元素。

由于这种意图/设计,如果要get()对存储对象的引用,然后对其进行变异,则可能是由于Set可能会受阻并可能导致意外行为。

来自JavaDocs


如果将可变对象用作set元素,则必须格外小心。如果对象的值更改为影响相等比较的方式,而该对象是集合中的元素,则不指定集合的​​行为。


如何:

现在已经介绍了Streams,可以执行以下操作

mySet.stream()
.filter(object -> object.property.equals(myProperty))
.findFirst().get();


评论


由于Stream API的支持。尽管如此,仍然不建议使用get(),而应使用orElse()或ifPresent()。

–alistairv
12月11日在22:53



#9 楼

Object objectToGet = ...
Map<Object, Object> map = new HashMap<Object, Object>(set.size());
for (Object o : set) {
    map.put(o, o);
}
Object objectFromSet = map.get(objectToGet);


如果只执行一次操作,将不会很好地执行,因为您将遍历所有元素,但是在大集合上执行多次检索时,您会注意到其中的区别。

#10 楼

您可以使用Iterator类

import java.util.Iterator;
import java.util.HashSet;

public class MyClass {
 public static void main(String[ ] args) {
 HashSet<String> animals = new HashSet<String>();
animals.add("fox");
animals.add("cat");
animals.add("dog");
animals.add("rabbit");

Iterator<String> it = animals.iterator();
while(it.hasNext()) {
  String value = it.next();
  System.out.println(value);   
 }
 }
}


#11 楼

为此,您最好使用Java HashMap对象http://download.oracle.com/javase/1,5.0/docs/api/java/util/HashMap.html

#12 楼

我知道,这是很久以前问过的,但是,如果有人有兴趣,这是我的解决方案-由HashMap支持的自定义集类: >
您可以轻松实现所有其他Set方法。

评论


最好包括示例而不是仅链接到一个示例。

–所有工人都是必不可少的
2014-2-10 22:34

@Lukas Z.您的add()不能确保该元素是否存在于“集合”中。因此,根据您的实现,允许重复!这显然违反了集合的原理。

–StudentAccount4
8月13日13:10

#13 楼

去过也做过!!如果您使用的是番石榴,将其转换为地图的快速方法是:

Map<Integer,Foo> map = Maps.uniqueIndex(fooSet, Foo::getKey);


#14 楼

如果要从HashSet中获取第n个元素,则可以采用以下解决方案,
这里我在HashSet中添加了ModelClass的对象。

#15 楼

如果看一下java.util.HashSet的实现的前几行,您会看到:直接使用与键相同的值,您将获得想要的效果并节省一些内存。

#16 楼

似乎使用的正确对象是来自guava的Interner:


为其他不可变类型提供与String.intern()等效的行为。常见的实现可从Interners
类中获得。


它还具有一些非常有趣的杠杆,例如concurrencyLevel或使用的引用类型(可能值得注意的是它没有提供SoftInterner,我认为它比WeakInterner更有用)。

#17 楼

那么使用Arrays类呢?

import java.util.Arrays;
import java.util.List;
import java.util.HashSet;
import java.util.Arrays;

public class MyClass {
    public static void main(String args[]) {
        Set mySet = new HashSet();
        mySet.add("one");
        mySet.add("two");
        List list = Arrays.asList(mySet.toArray());
        Object o0 = list.get(0);
        Object o1 = list.get(1);
        System.out.println("items " + o0+","+o1);
    }
}


输出:
项目一,二

评论


因为您没有任何索引来提取对象,所以只有“一个”。另外,它效率低下。正确的方法是使用地图。

– zakmck
10月5日下午16:36

@zakmck我运行示例,结果是项目一,二。此外,该问题并未询问有关性能的问题。

–速度
10月6日13:10

你没明白这一点。您在这个错误的示例中得到了结果,但是在现实生活中,您想要这样做:gist.github.com/marco-brandizi/4cbbb54746e5200763886cdbfa4a1466,因为您想知道对象是否存在,如果是,请进行检索。您没有索引,即使您创建了列表并用于搜索原始o,这也将是非常糟糕的代码,并且即使没有明确要求,您也应该假设人们需要有效的解决方案。

– zakmck
10月7日,11:04

#18 楼

因为Set的任何特定实现都可能是随机访问,也可能不是随机访问。

您总是可以获取迭代器并逐步遍历Set,使用迭代器的next()方法返回找到的结果。相等的元素。无论实现如何,此方法均有效。如果实现不是随机访问(使用链接列表支持的Set),则接口中的get(E element)方法将具有欺骗性,因为它必须迭代集合以找到要返回的元素,而get(E element)似乎暗示了这一点。 Set可能会直接跳到要获取的元素上。

contains()当然可以或可以不必做相同的事情,具体取决于实现方式,但是名称并不似乎很容易引起同样的误会。

评论


get()方法可以做的任何事情已经由contains()方法完成。您必须先获取包含的对象并调用其.equals()方法,才能实现contains()。 API设计人员似乎对将get()添加到java.util.List毫无疑虑,尽管在某些实现中会很慢。

–布莱恩·林克(Bryan Rink)
13-10-25在22:14

我不认为这是真的。两个对象通过等号可以相等,但通过==可以不相等。如果您有对象A,以及包含对象B和A.equals(B)但A!= B的集合S,并且想要获取对B的引用,则可以调用S.get(A)来获取对B的引用。 B,假设您有一个具有List的get方法的语义的get方法,这与检查S.contains(A)(它会那样)是不同的用例。这甚至不是集合的用例。

–汤姆·特雷桑斯基(Tom Tresansky)
2013年11月1日15:21

#19 楼

是的,请使用HashMap ...,但是以一种特殊的方式:我试图使用HashMap作为伪Set的陷阱是Map/Set的“实际”元素与“候选”元素(即使用的元素)之间可能的混淆测试是否已经存在equal元素。这远非万无一失,但会使您远离陷阱:

class SelfMappingHashMap<V> extends HashMap<V, V>{
    @Override
    public String toString(){
        // otherwise you get lots of "... object1=object1, object2=object2..." stuff
        return keySet().toString();
    }

    @Override
    public V get( Object key ){
        throw new UnsupportedOperationException( "use tryToGetRealFromCandidate()");
    }

    @Override
    public V put( V key, V value ){
       // thorny issue here: if you were indavertently to `put`
       // a "candidate instance" with the element already in the `Map/Set`: 
       // these will obviously be considered equivalent 
       assert key.equals( value );
       return super.put( key, value );
    }

    public V tryToGetRealFromCandidate( V key ){
        return super.get(key);
    }
}


然后执行以下操作: />但是,...您现在希望candidate以某种方式自毁,除非程序员实际上立即将其放在Map/Set中...您希望contains“污染” candidate,以便对其进行任何使用,除非它加入Map使其成为“ anthema”。也许您可以使SomeClass实现新的Taintable接口。

更令人满意的解决方案是GettableSet,如下所示。但是,要使此工作正常,您必须负责SomeClass的设计,以使所有构造函数都不可见(或...能够并愿意为其设计和使用包装器类):

SelfMappingHashMap<SomeClass> selfMap = new SelfMappingHashMap<SomeClass>();
...
SomeClass candidate = new SomeClass();
if( selfMap.contains( candidate ) ){
    SomeClass realThing = selfMap.tryToGetRealFromCandidate( candidate );
    ...
    realThing.useInSomeWay()...
}


实现:

public interface NoVisibleConstructor {
    // again, this is a "nudge" technique, in the sense that there is no known method of 
    // making an interface enforce "no visible constructor" in its implementing classes 
    // - of course when Java finally implements full multiple inheritance some reflection 
    // technique might be used...
    NoVisibleConstructor addOrGetExisting( GettableSet<? extends NoVisibleConstructor> gettableSet );
};

public interface GettableSet<V extends NoVisibleConstructor> extends Set<V> {
    V getGenuineFromImpostor( V impostor ); // see below for naming
}


您的NoVisibleConstructor类如下所示: br />
PS具有这样的NoVisibleConstructor类的一个技术问题:可能会反对这种类本质上是final,这可能是不希望的。实际上,您总是可以添加一个无参数的伪protected构造函数:

public class GettableHashSet<V extends NoVisibleConstructor> implements GettableSet<V> {
    private Map<V, V> map = new HashMap<V, V>();

    @Override
    public V getGenuineFromImpostor(V impostor ) {
        return map.get( impostor );
    }

    @Override
    public int size() {
        return map.size();
    }

    @Override
    public boolean contains(Object o) {
        return map.containsKey( o );
    }

    @Override
    public boolean add(V e) {
        assert e != null;
        V result = map.put( e,  e );
        return result != null;
    }

    @Override
    public boolean remove(Object o) {
        V result = map.remove( o );
        return result != null;
    }

    @Override
    public boolean addAll(Collection<? extends V> c) {
        // for example:
        throw new UnsupportedOperationException();
    }

    @Override
    public void clear() {
        map.clear();
    }

    // implement the other methods from Set ...
}


...至少可以让子类进行编译。然后,您必须考虑是否需要在子类中包括另一个getOrCreate()工厂方法。 set),以便您的set成员使用(如果可能的话-再次,使用包装类的范围,该类不在您的控制之下,或者已经具有基类,等等),以最大程度地实现隐藏:
class SomeClass implements NoVisibleConstructor {

    private SomeClass( Object param1, Object param2 ){
        // ...
    }

    static SomeClass getOrCreate( GettableSet<SomeClass> gettableSet, Object param1, Object param2 ) {
        SomeClass candidate = new SomeClass( param1, param2 );
        if (gettableSet.contains(candidate)) {
            // obviously this then means that the candidate "fails" (or is revealed
            // to be an "impostor" if you will).  Return the existing element:
            return gettableSet.getGenuineFromImpostor(candidate);
        }
        gettableSet.add( candidate );
        return candidate;
    }

    @Override
    public NoVisibleConstructor addOrGetExisting( GettableSet<? extends NoVisibleConstructor> gettableSet ){
       // more elegant implementation-hiding: see below
    }
}


...用法非常明显(在SomeClassstatic工厂方法内部):

protected SomeClass(){
    throw new UnsupportedOperationException();
}


评论


不。如果您确实想要一个新的数据结构来管理它,则应该扩展Set接口,例如,接口RetrievableElementsSet 扩展Set ,它应该具有一个新方法E get(E e),然后可以实现通过在内部使用HashMap作为RetrievableElementHasSet。这个SelfMappingHashMap不够抽象和干净,而不是这种混乱,直接使用Map / HashMap很快。

– zakmck
10月7日11:10

@zakmck首先,感谢您实际上对我的回答很感兴趣。重新阅读它,我认为您认为它是“混乱”是正确的。我不太了解您的推理或最终目的(“很快”?),但再次感谢您对此事进行了思考。

–麦克·啮齿动物
10月7日18:24

我的意思是“快速”。直接使用Map 是执行OP要求的快速方法。定义新的Set扩展名是一种更为纯粹的方法,它使“可从集合中检索对象”的抽象变得很明确,但是实现起来却更长。我最初的意思是,如果必须定义冗长的,更抽象的方式,则只有在正确完成后才有意义。

– zakmck
10月8日,0:11



#20 楼

哈希码的约定清楚地表明:


“如果根据Object方法,两个对象相等,则在两个对象中的每个对象上调用hashCode方法必须产生相同的整数结果” >不是所有字段。所以两个被认为相等的Foo对象实际上可以具有不同的值,这就是为什么我不能只使用foo。”


是错误的,您正在违约。如果我们看一下Set接口的“ contains”方法,就会发现:


如果此集合包含指定的元素,则返回true。正式地,More
,当且仅当该集合包含元素o <= null时,才返回true。 e == null:o.equals(e)


要实现所需的功能,可以在定义键的地方使用Map并使用定义对象的键的方式存储元素彼此不同或相等。

#21 楼

如果您拥有NavigableSet(例如,TreeSet),则可以执行以下操作:
public static <E> E get(NavigableSet<E> set, E key) {
    return set.tailSet(key, true).floor(key);
}

对于HashSet及其后代(例如LinkedHashSet),情况会有些棘手:
import java.util.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Test {
    private static final Field mapField;
    private static final Method hashMethod;
    private static final Method getNodeMethod;
    private static final Field keyField;
    static {
        try {
            mapField = HashSet.class.getDeclaredField("map");
            mapField.setAccessible(true);
            hashMethod = HashMap.class.getDeclaredMethod("hash", Object.class);
            hashMethod.setAccessible(true);
            getNodeMethod = HashMap.class.getDeclaredMethod("getNode",
                    Integer.TYPE, Object.class);
            getNodeMethod.setAccessible(true);
            keyField = Class.forName("java.util.HashMap$Node").getDeclaredField("key");
            keyField.setAccessible(true);
        } catch (ReflectiveOperationException e) {
            throw new RuntimeException(e);
        }
    }

    public static <E> E get(HashSet<E> set, E key) {
        try {
            Object map = mapField.get(set);
            Object hash = hashMethod.invoke(null, key);
            Object node = getNodeMethod.invoke(map, hash, key);
            if (node == null)
                return null;
            @SuppressWarnings("unchecked")
            E result = (E)keyField.get(node);
            return result;
        } catch (ReflectiveOperationException e) {
            throw new RuntimeException(e);
        }
    }

    public static <E> E get(NavigableSet<E> set, E key) {
        return set.tailSet(key, true).floor(key);
    }

    public static void main(String[] args) {
        HashSet<Integer> s = new HashSet<>();
//      HashSet<Integer> s = new LinkedHashSet<>();
//      TreeSet<Integer> s = new TreeSet<>();
        for (int i = 0; i < 100_000; i++)
            s.add(i);
        Integer key = java.awt.event.KeyEvent.VK_FIND;
        Integer hidden = get(s, key);
        System.out.println(key);
        System.out.println(hidden);
        System.out.println(key.equals(hidden));
        System.out.println(key == hidden);
    }
}


#22 楼

尝试使用数组:

ObjectClass[] arrayName = SetOfObjects.toArray(new ObjectClass[setOfObjects.size()]);


#23 楼

可能解决这种情况的快速帮助方法:

<T> T onlyItem(Collection<T> items) {
    if (items.size() != 1)
        throw new IllegalArgumentException("Collection must have single item; instead it has " + items.size());

    return items.iterator().next();
}


评论


奇怪的是,这个答案获得了如此之多的好评,因为它没有回答问题,甚至没有试图以任何方式解决它。

–大卫·康拉德(David Conrad)
16年11月1日在12:58

#24 楼

以下可能是一种方法

   SharedPreferences se_get = getSharedPreferences("points",MODE_PRIVATE);
   Set<String> main = se_get.getStringSet("mydata",null);
   for(int jk = 0 ; jk < main.size();jk++)
   {
      Log.i("data",String.valueOf(main.toArray()[jk]));
   }