Является список <Списком <Строка>> экземпляр Набора <Набор <T>>?

Более полное обсуждение ловушек использования regex для нахождения соответствия тегам может быть найдено в: http://faq.perl.org/perlfaq4.html#How_do_I_find_matchi . В частности, знайте, что вложенным тегам действительно нужен законченный синтаксический анализатор, чтобы интерпретироваться правильно.

Примечание, что чувствительность к регистру должна будет быть выключена для ответа на вопрос, как указано. В жемчуге это я модификатор:

$ echo "Data Data Data [Start] Data i want [End] Data" \
  | perl -ne '/\[start\](.*?)\[end\]/i; print "$1\n"'
 Data i want 

другой прием должен использовать *? квантор, который выключает жадность полученного соответствия. Например, если у Вас есть несоответствие [конец] тег:

Data Data [Start] Data i want [End] Data [end]

Вы, вероятно, не хотите получать:

 Data i want [End] Data

8
задан oxbow_lakes 20 November 2009 в 18:26
поделиться

6 ответов

public static <T> Set<T> makeSet(Collection<? extends Collection<T>> a_collection) {
    Iterator<? extends Collection<T>> it = a_collection.iterator();
    Set<T> result = new HashSet<T>();
    while (it.hasNext()) {
            result.addAll(it.next());
    }
    return result;
}
7
ответ дан 5 December 2019 в 06:37
поделиться

Нет, это не так.

Я бы изменил объявление быть

public static <T> Set<T> makeSet(Collection<? extends Collection<T>> a_collection) {
    ....
}

Два универсальных типа могут быть подтипами, только если аргументы типа идентичны (или с подстановочными знаками, поэтому Коллекция не является подтипом Коллекция . Проверьте раздел Подтипы в учебнике по универсальным шаблонам .

4
ответ дан 5 December 2019 в 06:37
поделиться

Это специализированная версия более общего вопроса: «Является ли Коллекция разновидностью Коллекции

Ответ (возможно, удивительный) нет .

Рассуждения хорошо сформулированы в контексте C ++ в C ++ FAQ . Это общий объектно-ориентированный вопрос, поэтому применимы те же общие рассуждения.

Например, рассмотрим альтернативную вселенную, где Collection является своего рода Collection . В этой вселенной вы могли бы сделать что-то вроде этого:

Collection<Circle> circles = new Collection<Circle>();
Collection<Shape> shapes = circles; // OK, we're in an alternate universe
shapes.Add(new Circle()); // OK, we're adding a circle to a collection of circles
shapes.Add(new Square()); // Asplode!  We just added a square to a collection of circles.

Что происходит, когда Квадрат, Форма, добавляется в коллекцию фигур, которая на самом деле представляет собой набор кругов? Нет хорошего ответа.

То же самое относится к Collection > и Коллекция <Коллекция > . Коллекция <Список > не является разновидностью Коллекции > , потому что не заменяет на Сборник <Сборник > . Queue может быть добавлен в коллекцию коллекций, но не может быть добавлен в коллекцию List .

3
ответ дан 5 December 2019 в 06:37
поделиться

Я почти ненавижу публиковать правильный ответ, потому что это так некрасиво, но, поскольку в трех основных ответах этот вопрос пропущен, я чувствую себя обязанным.

public static <T> Set<T> makeSet(
    Collection<? extends Collection<? extends T>> coll)

Вы прочитали правильно. Два "? Extends" s. В противном случае вы не сможете соединить List и List вместе, чтобы получить Set , что логически должно быть возможным.

Как только вы добираетесь до дженериков, вложенных внутри дженериков, все всегда становится неприятно. ] Вы можете быть полностью прощены за то, что выбрали более простой ответ. :) Просто знайте, что это не всегда будет работать там, где логически должно быть.

Между прочим, с Google Collections вы можете использовать Iterables.concat (...) для выполнения this или ImmutableSet.copyOf (Iterables.concat (...)) , если вам нужна де-дублирование.

3
ответ дан 5 December 2019 в 06:37
поделиться

Именно такие вещи привели к разработке Java 1.0 для упрощения всего тупого создания шаблонов C ++. Вы добавляете 5 уровней сложности, чтобы избежать одного глупого приведения из набора объектов в набор вашего конкретного экземпляра. Хорошо, хорошо, если вы обнаружите, что ведете кастинг повсюду и делаете свой код некрасивым, но на самом деле я уверен, что это происходит примерно раз в 500 тыс. Строк кода. Да, да, хорошо, что мы можем найти такие технические детали, но действительно ли ваш код становится более удобным в сопровождении, когда вы начинаете идти по этому пути?

0
ответ дан 5 December 2019 в 06:37
поделиться

Ваша подпись должна быть:

public static <T> Set<T> makeSet(Collection<? extends Collection<T>> coll);

Обычно List - это , а не подтип из List просто потому, что S является подтипом T . Это свойство называется ковариацией , а в Java универсальные типы не являются ковариантными (другие языки, такие как scala , содержат ковариантные универсальные типы).

Что вы не сработало, потому что должна быть возможность добавить любую Collection в Collection > , поэтому, например, с вашей подписью это будет допустимая реализация:

public static <T> Set<T> makeSet(Collection<Collection<T>> coll) {
    coll.add(new HashSet<T>());
    return null;
}

Но затем вызов этого метода следующим образом:

List<List<String>> outside = new LinkedList<List<String>>();
makeSet(outside); //actually this line will not compile!
List<String> oops = outside.get(0); //oh dear - it's a HashSet

Так приводит ли это к той же проблеме? НЕТ! Причина в том, что компилятор не позволит вам добавить что-либо в коллекцию, параметризованную для неизвестного типа:

public static <T> Set<T> makeSet(Collection<? extends Collection<T>> coll) {
    coll.add(new HashSet<T>()); //this line will not compile
    return null;
}

Наличие подстановочных знаков было необходимо в первую очередь для того, чтобы вы могли делать такие вещи, как то, что вы хотите, вероятно, лучше всего продемонстрировано тем, метод Collection.addAll был сгенерирован таким образом, чтобы List .addAll (List ) был разрешен:

boolean addAll(Collection<? extends T> coll)
8
ответ дан 5 December 2019 в 06:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: