我试图找到从x开始从集合中获取n个元素的最优雅方式。我的结论是使用流:
Set<T> s;
Set<T> subS = s.stream().skip(x).limit(n).collect(Collectors.toSet());
这是这样做的最好方法吗?有什么缺点吗?
答案 0 :(得分:11)
答案 1 :(得分:8)
使用Guava,Iterables.limit(s, 20)
。
答案 2 :(得分:5)
您的代码不起作用。
Set<T,C> s; Set<T,C> subS = s.stream().skip(x).limit(n).collect(Collectors.toSet());
什么是Set<T,C>
? Set
包含给定类型的元素,那么两个类型参数应该是什么意思?
此外,如果您有Set<T>
,则表示您没有已定义的订单。 “从x开始的集合中的n个元素”在Set
的上下文中没有意义。有一些专门的Set
实现有一个订单,例如排序或保留插入顺序,但由于您的代码没有声明这样的先决条件,但似乎应该在任意Set
上工作,因此必须将其视为已损坏。
如果您想根据订单处理Set
的一小部分,您必须先冻结订单:
Set<T> s;
List<T> frozenOrder=new ArrayList<>(s);
如果在Set
的创建时间修复了任何订单或任意订单,则列表将有一个订单ArrayList
,之后不会改变
然后,提取它的片段很容易:
List<T> sub=frozenOrder.subList(x, Math.min(s.size(), x+n));
如果您愿意,也可以将其转换回Set
:
Set<T> subSet=new HashSet<>(sub);
也就是说,处理由位置数给出的Set
的一部分是相当不寻常的。
答案 3 :(得分:1)
一套 - 以其原始方式 - 不打算有序元素,因此你不能从元素x开始。 SortedSet可能是&#34; set&#34;你想用。
我首先将其转换为List,例如
new ArrayList(s).subList(<index of x>, <index of x + n>);
但它可能会对性能产生非常不利的影响。在这种情况下,必须存储ArrayList以检索下一个subList,因为没有显式顺序,并且下次调用new ArrayList(s)
时隐式顺序可能会更改。
答案 4 :(得分:1)
使用Stream
很好。我可以看到的一个缺点并非所有Set
的实现都是有序的,例如HashSet
未订购,LinkedHashSet
。因此,您可能会在不同的运行中得到不同的结果集。
答案 5 :(得分:1)
首先,不是为了获取它的特定元素而设置的 - 你应该使用sortedSet或ArrayList。
但是如果必须获取集合的元素,则可以使用以下代码 迭代集合:
int c = 0;
int n = 50; //Number of elements to get
Iterator<T> iter = set.iterator();
while (c<n && iter.hasNext()) {
T t = iter.next();
list.add(t);
c++;
}
答案 6 :(得分:0)
你可以迭代集合并收集前n个元素:
int n = 0;
Iterator<T> iter = set.iterator();
while (n < 8 && iter.hasNext()) {
T t = iter.next();
list.add(t);
n++;
}
好处是它应该比更通用的解决方案更快。
缺点是它比你建议的更冗长。