将Set转换为List而不创建新List

时间:2012-01-17 09:40:05

标签: java performance list set

我使用此代码将Set转换为List

Map<String, List> mainMap = new HashMap<String, List>();

for(int i=0; i<something.size(); i++){
  Set set = getSet(...); //returns different result each time
  List listOfNames = new ArrayList(set);
  mainMap.put(differentKeyName,listOfNames);
}

我想避免在循环的每次迭代中创建一个新列表。这可能吗?

15 个答案:

答案 0 :(得分:742)

您可以使用List.addAll()方法。它接受Collection作为参数,你的集合是Collection。

List<String> mainList = new ArrayList<String>();
mainList.addAll(set);

编辑:作为对问题编辑的回复。
很容易看出,如果你想要Map List作为值,为了得到k个不同的值,你需要创建k个不同的列表。
因此:你根本无法避免创建这些列表,必须创建列表。

可能的解决方法:
将您的Map声明为Map<String,Set>Map<String,Collection>,然后插入您的设置。

答案 1 :(得分:390)

使用构造函数转换它:

List<?> list = new ArrayList<?>(set);

答案 2 :(得分:76)

同样来自Guava Collect库,您可以使用newArrayList(Collection)

Lists.newArrayList([your_set])

这与 amit 的上一个答案非常相似,只是您不需要声明(或实例化)任何list个对象。

答案 3 :(得分:37)

我们可以在Java 8中使用以下一个班轮:

List<String> list = set.stream().collect(Collectors.toList());

以下是一个小例子:

public static void main(String[] args) {
        Set<String> set = new TreeSet<>();
        set.add("A");
        set.add("B");
        set.add("C");
        List<String> list = set.stream().collect(Collectors.toList());
}

答案 4 :(得分:18)

  

最简单的解决方案

我想要一种非常快速的方法将我的设置转换为List并返回它,所以在一行中我做了

polygon.velocity({
   tween: ["0 0 439.837891 0 720 1024 0 1024", "0 0 720 0 720 1024 0 1024"]
}, {
   duration: 500,
   progress: function(elements, complete, remaining, start, tweenValue) {
      elements[0].setAttribute("points", tweenValue);
   }
});

答案 5 :(得分:6)

您可以使用以下一行更改:Arrays.asList(set.toArray(new Object[set.size()]))

Map<String, List> mainMap = new HashMap<String, List>();

for(int i=0; i<something.size(); i++){
  Set set = getSet(...); 
  mainMap.put(differentKeyName, Arrays.asList(set.toArray(new Object[set.size()])));
}  

答案 6 :(得分:4)

我愿意:

Map<String, Collection> mainMap = new HashMap<String, Collection>();

for(int i=0; i<something.size(); i++){
  Set set = getSet(...); //return different result each time
  mainMap.put(differentKeyName,set);
}

答案 7 :(得分:3)

Java 8提供了使用流的选项,您可以从Set<String> setString获取列表:

List<String> stringList = setString.stream().collect(Collectors.toList());

虽然现在的内部实现提供了ArrayList的实例:

public static <T>
    Collector<T, ?, List<T>> toList() {
        return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
                                   (left, right) -> { left.addAll(right); return left; },
                                   CH_ID);
    }

但JDK不保证。如上所述here

  

不保证类型,可变性,可序列性或   返回列表的线程安全性;如果更多控制返回   列表是必需的,使用toCollection(供应商)。

如果你想确定总是那么你可以专门请求一个实例:

List<String> stringArrayList = setString.stream()
                     .collect(Collectors.toCollection(ArrayList::new));

答案 8 :(得分:2)

我创建简单的static方法:

public static <U> List<U> convertSetToList(Set<U> set)
{
    return new ArrayList<U>(set);
}

...或者如果您想设置List的类型,您可以使用:

public static <U, L extends List<U>> List<U> convertSetToList(Set<U> set, Class<L> clazz) throws InstantiationException, IllegalAccessException
{
    L list = clazz.newInstance();
    list.addAll(set);
    return list;
}

答案 9 :(得分:2)

最近我发现了这个:

var canvas = element(by.id('remoteTerminalCanvas'));
browser.wait(function () {
    return canvas.evaluate("vm.hasImage").then(function (hasImage) { 
        return hasImage;
    });
}, 5000);

答案 10 :(得分:1)

我发现这很好用,可以从Set中创建List。

ArrayList < String > L1 = new ArrayList < String > ();
L1.addAll(ActualMap.keySet());
for (String x: L1) {
    System.out.println(x.toString());
}

答案 11 :(得分:1)

由于到目前为止尚未提及它,因此从Java 10开始,您可以使用新的copyOf工厂方法:

List.copyOf(set);

来自Javadoc

  

以迭代顺序返回包含给定Collection元素的unmodifiable List

答案 12 :(得分:0)

为了完整性...

假设您确实 确实希望将Map值视为列表,但是要避免每次都将Set复制到列表中。

例如,也许您正在调用一个创建Set的库函数,但是您将Map 结果传递给了一个仅接受Map 您知道它对列表执行的操作同样适用于任何集合(因此也适用于任何集合)。而出于某种原因,您需要避免将每个Set复制到列表的速度/内存开销。

在这种特殊情况下,根据库函数需要从列表中删除的行为(可能是未知的),您可以在每个Set上创建一个列表 view 。请注意,这本质上是不安全的(因为可能不知不觉地更改了每个List的库函数要求),因此应首选其他解决方案。但是,这是您的操作方式。

您将创建一个实现List接口的类,在构造函数中使用Set并将该Set分配给一个字段,然后使用该内部Set来实现List API(在可能的范围内,并按需要执行)。

请注意,某些List行为如果不将元素存储为List便无法模仿,而某些行为则只能部分模仿。同样,此类通常不能安全地替代List。尤其是,如果您知道用例需要与索引相关的操作或对列表进行静音,则这种方法会很快消失。

public class ListViewOfSet<U> implements List<U> {
    private final Set<U> wrappedSet;
    public ListViewOfSet(Set<U> setToWrap) { this.wrappedSet = setToWrap; }

    @Override public int size() { return this.wrappedSet.size(); }
    @Override public boolean isEmpty() { return this.wrappedSet.isEmpty(); }
    @Override public boolean contains(Object o) { return this.wrappedSet.contains(o); }
    @Override public java.util.Iterator<U> iterator() { return this.wrappedSet.iterator(); }
    @Override public Object[] toArray() { return this.wrappedSet.toArray(); }
    @Override public <T> T[] toArray(T[] ts) { return this.wrappedSet.toArray(ts); }
    @Override public boolean add(U e) { return this.wrappedSet.add(e); }
    @Override public boolean remove(Object o) { return this.wrappedSet.remove(o); }
    @Override public boolean containsAll(Collection<?> clctn) { return this.wrappedSet.containsAll(clctn); }
    @Override public boolean addAll(Collection<? extends U> clctn) { return this.wrappedSet.addAll(clctn); }
    @Override public boolean addAll(int i, Collection<? extends U> clctn) { throw new UnsupportedOperationException(); }
    @Override public boolean removeAll(Collection<?> clctn) { return this.wrappedSet.removeAll(clctn); }
    @Override public boolean retainAll(Collection<?> clctn) { return this.wrappedSet.retainAll(clctn); }
    @Override public void clear() { this.wrappedSet.clear(); }
    @Override public U get(int i) { throw new UnsupportedOperationException(); }
    @Override public U set(int i, U e) { throw new UnsupportedOperationException(); }
    @Override public void add(int i, U e) { throw new UnsupportedOperationException(); }
    @Override public U remove(int i) { throw new UnsupportedOperationException(); }
    @Override public int indexOf(Object o) { throw new UnsupportedOperationException(); }
    @Override public int lastIndexOf(Object o) { throw new UnsupportedOperationException(); }
    @Override public ListIterator<U> listIterator() { throw new UnsupportedOperationException(); }
    @Override public ListIterator<U> listIterator(int i) { throw new UnsupportedOperationException(); }
    @Override public List<U> subList(int i, int i1) { throw new UnsupportedOperationException(); }
}

...
Set set = getSet(...);
ListViewOfSet listOfNames = new ListViewOfSet(set);
...

答案 13 :(得分:0)

您将 override fun showCompletedDialog() { DfuBaseService.PROGRESS_COMPLETED val dialog = AlertDialog.Builder(this) .setTitle(getString((R.string.dfu_completed_title))) .setMessage(getString(R.string.dfu_completed_message)) .setPositiveButton(R.string.dfu_completed_ok) { dialog, _ -> transaction(listFragment, R.id.cvCentral) supportFragmentManager.findFragmentById(R.id.upperContainer)?.let { supportFragmentManager.beginTransaction().remove(it).commit() setNavigationTitle(getString(R.string.title_header_devices)) } upperContainer.visibility = View.GONE Handler().postDelayed({ onBackPressed() dialog.dismiss() }, 400) } dialog.setCancelable(false) dialog.show() } 转换为Set,而没有添加仅用于存储在地图中的订购信息(例如排序)。

由于List是无序的,并且没有添加任何排序信息,因此Set不应使用,因为它将包含随机排序的数据,并且与排序数据有关的所有方法都将是模棱两可的。 / p>

您应该改用List界面,该界面在地图中同时接受CollectionSet。这样,由于您使用多态性而不是复制数据,因此不需要额外的内存。

List

免责声明:我对similar答案的编辑被拒绝,因此我添加了自己的答案以及其他信息

答案 14 :(得分:-15)

Map<String, List> mainMap = new HashMap<String, List>();

for(int i=0; i<something.size(); i++){
  Set set = getSet(...); //return different result each time
  mainMap.put(differentKeyName, new ArrayList(set));
}