给定一个简单的Set<T>
方法,从中获取任何值的好方法(快速,几行代码)是Set
什么?
使用List
,很容易:
List<T> things = ...;
return things.get(0);
但是,对于Set
,没有.get(...)
方法,因为Set
s没有排序。
Answers:
Set
我所知道的任何实现,这最多是O(log n)。
LinkedHashSet
。轻松解决。)
由于存在流,因此也可以这样做,但是必须使用class java.util.Optional
。Optional
是元素或显式无元素(避免使用Nullpointer)的包装器类。
//returns an Optional.
Optional <T> optT = set.stream().findAny();
//Optional.isPresent() yields false, if set was empty, avoiding NullpointerException
if(optT.isPresent()){
//Optional.get() returns the actual element
return optT.get();
}
编辑:我Optional
经常使用自己:有一种方法可以访问元素或获取默认值(如果不存在):
optT.orElse(other)
返回元素,或者如果不存在,则返回other
。other
可能是null
,顺便说一句。
set.iterator().next();
。
从集合或集合中获取任何元素似乎是一种不常见的需求-即使不是任意的或折衷的-但是,例如当人们需要计算Map中的键或值对象的统计信息并且必须初始化min /最大值。在更新每个元素的最小/最大值之前,将使用Set / Collection中的any元素(由Map.keySet()或Map.values()返回)进行初始化。
那么,面对这个问题并试图保持较小的内存和执行时间以及清晰的代码时,人们有什么选择呢?
通常,您会得到通常的结果:“将Set转换为ArrayList并获取第一个元素”。大!另一个数百万个项目的数组和额外的处理周期,用于从Set中检索对象,分配数组并进行填充:
HashMap<K,V> map;
List<K> list = new ArrayList<V>(map.keySet()); // min/max of keys
min = max = list.get(0).some_property(); // initialisation step
for(i=list.size();i-->1;){
if( min > list.get(i).some_property() ){ ... }
...
}
或者可以使用带有迭代器的循环,使用标志来表示需要初始化min / max,并使用条件语句来检查是否为循环中的所有迭代设置了该标志。这意味着很多条件检查。
boolean flag = true;
Iterator it = map.keySet().iterator();
while( it.hasNext() ){
if( flag ){
// initialisation step
min = max = it.next().some_property();
flag = false;
} else {
if( min > list.get(i).some_property() ){ min = list.get(i).some_property() }
...
}
}
或者在循环外进行初始化:
HashMap<K,V> map;
Iterator it = map.keySet().iterator();
K akey;
if( it.hasNext() ){
// initialisation step:
akey = it.next();
min = max = akey.value();
do {
if( min > list.get(i).some_property() ){ min = akey.some_property() }
} while( it.hasNext() && ((akey=it.next())!=null) );
}
但是,每当需要最小/最大时,代表程序员(以及代表JVM设置Iterator)的所有这些操作真的值得吗?
来自javally正确的运动的建议很可能是:“将您的Map包裹在一个类中,该类在放置或删除时跟踪最小值和最大值!”。
根据我的经验,还有另一种情况,即仅需要地图中的任何物品。这是当地图包含具有共同属性的对象时-该映射中的所有对象都相同-并且您需要读取该属性。例如,假设有一个具有相同直方图的容纳箱的图,它们具有相同的维数。给定这样一个Map,您可能需要知道Map中任何Histobin的维数,以便创建另一个具有相同维数的Histobin。我是否需要再次设置迭代器,并在调用next()一次后将其处置?对于这种情况,我将跳过javally正确人士的建议。
而且,如果在获取任何元素时遇到的所有麻烦导致内存不足,并且CPU周期增加,那么为了获得难以获得的任何元素而必须编写的所有代码呢?
我们需要任何要素。把它给我们!
iterator().next()
。(这就是为什么我们没有一个getFirst(Iterable<E>)
,只是一个getFirst(Iterable<E>, E default)
。)