Преобразование LinkedHashSet в ArrayList или просто использование ArrayList

Рассмотрим следующий код:

final Set<String> allPaths = new HashSet<String>();
for (final String path: paths) {
        allPaths.add(path);
}
final MyData d = new MyData(new ArrayList<String>(allPaths));

MyData - это какой-то класс, который я не должен трогать. Он должен получить ArrayList в качестве аргумента. До этого дня мы использовали этот способ, потому что нас не заботил порядок, поэтому мы использовали Set (чтобы не было дублирования). Но теперь я хотел бы сохранить порядок элементов, поэтому после некоторых исследований я обнаружил, что для этого я могу использовать структуру данных LinkedHashSet. Так я и сделал:

final LinkedHashSet<String> allPaths = new LinkedHashSet<String>();
for (final String path: paths) {
        allPaths .add(path);
}
final MyData d = new MyData(new ArrayList<String>(allPaths));

Проблема в том, что я не знаю, как преобразовать LinkedHashSet в ArrayList. Кроме того, я подумал об использовании ArrayList вместо LinkedHashSet, поэтому мне не нужно будет его преобразовывать, но мне придется перебирать массив (O(n)).

Какой хороший, чистый и эффективный способ я должен использовать?


person TTaJTa4    schedule 30.12.2018    source источник
comment
Возможный дубликат Преобразовать набор в список без создания нового списка   -  person Nicholas K    schedule 30.12.2018
comment
Измените MyData на использование Collection. Почему изначально было жестко закодировано использование ArrayList?   -  person Elliott Frisch    schedule 30.12.2018
comment
Что не так с тем, как вы это делаете? Не должно быть разницы в создании ArrayList между использованием LinkedHashSet и использованием любого другого Set, за исключением того, что он будет использовать правильный порядок итераций.   -  person RealSkeptic    schedule 30.12.2018
comment
в чем проблема с тем, что ты делаешь прямо сейчас? Я имею в виду, что создание списка из набора — это в основном то, что вы сделали, и это нормально. какое это имеет отношение к O(n)? Я не понимаю этого.   -  person UninformedUser    schedule 30.12.2018
comment
... и мне интересно, что такое paths в вашем коде? Это List или Set?   -  person Naman    schedule 30.12.2018
comment
... или paths вообще массив?   -  person Dorian Gray    schedule 30.12.2018
comment
@ElliottFrisch Я (частично) согласен с вами, но, поскольку он говорит, что MyData - это какой-то класс, который я не должен трогать, изменение подписи конструктора, похоже, не вариант. Я согласен лишь частично, потому что если конструктору требуются упорядоченные данные, общий аргумент Collection этого не выражает.   -  person Dorian Gray    schedule 30.12.2018
comment
@DorianGray Я сделал это комментарием, и теперь я собираюсь спросить: почему MyData — это какой-то класс, который я не должен трогать.? List (или Iterable) будет лучше, чем ArrayList. Но поскольку мы не можем видеть MyData, я по-прежнему не убежден в его неприкосновенности.   -  person Elliott Frisch    schedule 30.12.2018
comment
@ElliottFrisch Я думаю, он использует какую-то стороннюю библиотеку   -  person Dorian Gray    schedule 30.12.2018


Ответы (4)


Просто используйте метод public boolean addAll(Collection<? extends E> c) в списке массивов, он принимает любые Collection.

У вас есть LinkedHashSet:

final LinkedHashSet<String> allPaths = new LinkedHashSet<String>();
for (final String path: paths) {
        allPaths .add(path);
}

а затем выполните (вы можете использовать это, даже если mylist не пусто):

List<String> myList = new ArrayList<>();
mylist.addAll(allPaths);

или для еще более простого подхода:

List<String> myList = new ArrayList<>(allPaths);
person Daniel B.    schedule 30.12.2018
comment
знает ли new ArrayList<String>(<???>), как обращаться с коллекцией (например, LinkedHashSet)? Если да, то будет ли работать мой способ? - person TTaJTa4; 30.12.2018
comment
@TTaJTa4 да, в этом весь смысл интерфейса коллекции. Это абстрактная идея, имеющая множество реализаций, но в основном это одно и то же, набор вещей. Java использует Collection вместо жестко закодированных реализаций (например, ArrayList), чтобы иметь возможность переключаться с одной реализации на другую - точно так же, как в вашем случае, когда вы хотите использовать LinkedHashSet вместо HashSet, без необходимости переписывать метод/класс, в который вы передаете аргумент. - person Daniel B.; 30.12.2018
comment
addAll - это просто дополнение к тому, что уже сделал ОП. Нет необходимости использовать его, его можно использовать так, как он был изначально. - person RealSkeptic; 30.12.2018
comment
@RealSkeptic, который вы вызываете, использует метод addAll, даже если список не пуст, на случай, если он ему понадобится, как я уже упоминал в своем ответе. - person Daniel B.; 30.12.2018
comment
Мне интересно, что отличается в вашем ответе от того, что он уже делает в своем вопросе?! - person UninformedUser; 30.12.2018
comment
Это не так, он просто спросил, можно ли это сделать, потому что он не знал, как конвертировать коллекции, я показал ему пару вариантов - person Daniel B.; 30.12.2018

Почему бы вам просто не преобразовать paths в LinkedHashSet вот так (при условии, что paths — это Коллекция?

final MyData d = new MyData(new ArrayList<>(new LinkedHashSet<>(paths)));

В случае, если paths является массивом, вы можете использовать Arrays.asList(paths) внутри приведенного выше преобразования.

person Dorian Gray    schedule 30.12.2018

@TTaJTa4 you can use the code below as an example. Both ways are fine.



import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.Set;

public class ConvertLinkedHashSetToArrayList
{

  public static void main(String[] args)
  {
    Set<String> testStrings = new LinkedHashSet<>();
    testStrings.add("String 1");
    testStrings.add("String 2");
    testStrings.add("String 3");
    testStrings.add("String 4");
    testStrings.add("String 5");

    System.out.println("** Printing LinkedHashSet: " + testStrings);
    ArrayList<String> linkedHashSetToArrayList1 = new ArrayList<>(testStrings);
    System.out.println("** Printing linkedHashSetToArrayList1:" + 
    linkedHashSetToArrayList1);

    ArrayList<String> linkedHashSetToArrayList2 = new ArrayList<>();
    linkedHashSetToArrayList2.addAll(testStrings);
    System.out.println("** Printing linkedHashSetToArrayList2:" + 
    linkedHashSetToArrayList2);
  }
}

Результаты такие:

** Printing LinkedHashSet: [String 1, String 2, String 3, String 4, String 5]
** Printing linkedHashSetToArrayList1:[String 1, String 2, String 3, String 4, String 5]
** Printing linkedHashSetToArrayList2:[String 1, String 2, String 3, String 4, String 5]

Перейдите по ссылке GitHub, чтобы просмотреть полный проект Java: пример GitHub

person Dilanka M    schedule 30.12.2018

Если paths является коллекцией, вы можете получить список массивов без дубликатов:

ArrayList<String> p = paths.stream().distinct().collect(Collectors.toCollection(ArrayList::new));

Если paths является массивом:

ArrayList<String> p = Stream.of(paths).distinct().collect(Collectors.toCollection(ArrayList::new));

person c0der    schedule 30.12.2018