Более полное обсуждение ловушек использования 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
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;
}
Нет, это не так.
Я бы изменил объявление быть
public static <T> Set<T> makeSet(Collection<? extends Collection<T>> a_collection) {
....
}
Два универсальных типа могут быть подтипами, только если аргументы типа идентичны (или с подстановочными знаками, поэтому Коллекция
не является подтипом Коллекция
. Проверьте раздел Подтипы в учебнике по универсальным шаблонам .
Это специализированная версия более общего вопроса: «Является ли Коллекция
разновидностью Коллекции
?»
Ответ (возможно, удивительный) нет .
Рассуждения хорошо сформулированы в контексте 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
.
Я почти ненавижу публиковать правильный ответ, потому что это так некрасиво, но, поскольку в трех основных ответах этот вопрос пропущен, я чувствую себя обязанным.
public static <T> Set<T> makeSet(
Collection<? extends Collection<? extends T>> coll)
Вы прочитали правильно. Два "? Extends" s. В противном случае вы не сможете соединить List
Как только вы добираетесь до дженериков, вложенных внутри дженериков, все всегда становится неприятно. ] Вы можете быть полностью прощены за то, что выбрали более простой ответ. :) Просто знайте, что это не всегда будет работать там, где логически должно быть.
Между прочим, с Google Collections вы можете использовать Iterables.concat (...)
для выполнения this или ImmutableSet.copyOf (Iterables.concat (...))
, если вам нужна де-дублирование.
Именно такие вещи привели к разработке Java 1.0 для упрощения всего тупого создания шаблонов C ++. Вы добавляете 5 уровней сложности, чтобы избежать одного глупого приведения из набора объектов в набор вашего конкретного экземпляра. Хорошо, хорошо, если вы обнаружите, что ведете кастинг повсюду и делаете свой код некрасивым, но на самом деле я уверен, что это происходит примерно раз в 500 тыс. Строк кода. Да, да, хорошо, что мы можем найти такие технические детали, но действительно ли ваш код становится более удобным в сопровождении, когда вы начинаете идти по этому пути?
Ваша подпись должна быть:
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
был разрешен:
boolean addAll(Collection<? extends T> coll)