пятница, 15 октября 2010 г.

Java хитрости: На какие грабли можно наступить, если не любишь массивы.

Если честно я очень люблю листы из Java Collection Framework. Работать с ними гораздо удобнее, чем ** себе мозг с массивами, поэтому я довольно часто пользовалась методом Arrays.asList, не особо задумываясь, что при этом происходит. Точнее я просто предполагала, что оно делает нечто вроде:

List<String> list = new ArrayList<String>();
    for (String a : array)
        list.add(a);

Однако сегодня у меня наконец дошли руки посмотреть, что никакого копирования на самом деле не происходит. Arrays реализует свой ArrayList который пишет в массив, переданный ему в качестве параметра. То есть все изменения в листе приводят к изменению в массиве и наоборот. Ну и, очевидно, возвращаемый этим методом лист не является полноправной реализацией интерфейса List, ибо методы add и remove поддерживать он не может. Странно, что я ни разу не наступила до этого на грабли с удалением:)

Кстати, еще одно, уже приятное открытие - иногда очень-очень хочется создавать листы на манер массивов. А-ля:

List<A> list = new ArrayList<A>(a1, a2, a3, a4);

И вот возможный вариант:

List<A> list = Arrays.asList(a1, a2, a3, a4);

Эх, все-таки полезно читать джава доки :)

вторник, 12 октября 2010 г.

@g

Java хитрости: как удалить все элементы А из коллекции.

Мне всегда казалось, что удалять все элементы А из коллекции с помощью цикла или итератора - это подозрительно некрасиво (ну неужели Collecion Framework
не предусматривает нормального способа это сделать?). Сегодня на меня снизошло откровение:

collection.removeAll(Collections.singleton(A));

Откровение номер два - оказывается метод removeAll совсем не так прост как изначально притворялся. Всегда думала, что он делает что-то вроде

boolean removeAll (Collection collection){
   for(E e: collection){
      this.remove(e);
   }
}

и ведь нифига :

public boolean removeAll(Collection c) {
   boolean modified = false;
   Iterator e = iterator();
   while (e.hasNext()) {
      if (c.contains(e.next())) {
         e.remove();
         modified = true;
      }
   }
   return modified;
}

вторник, 12 января 2010 г.

Eclipse RCP: резолвим и редактируем файлы

Ранее всю работу по резолвингу, открытию и редактированию файлов в своем Eclipse плагине я проворачивала через интерфейс IWorkspaceRoot. Из рута получала ссылку на проект, а дальше оставалась только радоваться удобству интерфейсов IFile, IResource, IProject и прочих.

Зарезолвленный таким образом файл открыть было проще простого:

IWorkbenchPage page = ...;
IFile file = ...;
IEditorDescriptor desc = PlatformUI.getWorkbench().getEditorRegistry().getDefaultEditor(file.getName());
page.openEditor(new FileEditorInput(file), desc.getId());

Первыми граблями на которые я наступила стала линка.

IFolder#createLink(IPath localLocation, int updateFlags,IProgressMonitor monitor);

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

IResource.REPLACE

Все бы ничего если бы мне вдруг не приспичило получить location этого одноименного файла (очень уж хотелось открыть этот файлик и поредактировать обычными средствами IO):) Так много я никогда не материлась, зато с тех пор я читаю доки внимательно, а не как обычно:) При использвании флага REPLACE одноименный файл замещается в воркспейсе линкой !
В итоге был сооружен костыль:

IWorkspaceRoot root = ;
IProject project = root.getProject(name);
IPath location = project.getLocation().append(fileName);

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

Ладно, с файлами которые (хотя бы просто географически) лежат внутри воркспейса все более или менее понятно. Но как открыть файл который лежит где-нибудь у черта на куличках? Лично я со своим воркспейс подходом к ресурсам впала в некоторый ступор :) Зарезолвить такой фал нельзя (то есть получить удобоваримую и такую милую сердцу ссылочку на IFile). В голове тут же пронеслась масса вариантов с созданием ссылки на удаленный файл, однако все оказалось куда проще:

IFileStore fileStore = EFS.getLocalFileSystem().getStore(fileToOpen.toURI());
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
IDE.openEditorOnFileStore( page, fileStore );

Заметьте, этот код откроет дефолтный эдитор, хотя там же в IDE есть метод для открытия файла по его URI, в эдиторе с заданным ID. Вобщем, настоятельно рекомендую поразглядывать классик IDE - можно узнать кое что полезное.

Пока все:)