Самый эффективный способ видеть, содержит ли ArrayList объект в Java

Возможно, вы захотите использовать время, доказанное xPDF , и производные инструменты для извлечения текста вместо этого, поскольку pyPDF2, похоже, имеет различные проблемы с сохранением текста.

. Долгий ответ заключается в том, что существует множество вариантов того, как текст кодируется внутри PDF и что он может потребоваться для декодирования самой строки PDF, тогда может потребоваться сопоставить с CMAP, тогда может потребоваться проанализировать расстояние между словами и буквами и т. д.

В случае повреждения PDF-файла (т. е. отображения правильного текста, но при копировании он дает мусор), и вам действительно нужно извлечь текст, тогда вы можете захотеть преобразовать PDF в изображение (используя ImageMagik ), а затем используйте Tesseract , чтобы получить текст с изображения с помощью OCR.

71
задан Svante 1 March 2009 в 19:24
поделиться

12 ответов

Это зависит от того, как эффективный Вам нужны вещи быть. Просто итерация по списку, ища элемент, который удовлетворяет определенное условие, является O (n), но ArrayList - также. Содержит, если Вы могли бы реализовать, Равняется методу. Если Вы не делаете этого в циклах или внутренних циклах, этот подход, вероятно, очень хорошо.

при реальной необходимости в очень эффективных скоростях поиска по всей стоимости необходимо будет сделать две вещи:

  1. Работа вокруг того, что класс сгенерирован: Запишите класс адаптера, который может перенести сгенерированный класс и который реализует , равняется () на основе тех двух полей (предполагающий, что они общедоступны). Не забывайте также реализовывать , хэш-код () (*)
  2. Переносит каждый объект с тем адаптером и поместил его в HashSet. HashSet.contains () имеет постоянное время доступа, т.е. O (1) вместо O (n).

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

<час> * () хэш-код Реализации () лучше всего сделан XOR'ing (^ оператор) хэш-коды тех же полей, которые Вы используете для, равняется реализации (но умножаются на 31 для сокращения шанса XOR получение 0)
102
ответ дан Community 7 November 2019 в 08:48
поделиться

Я сказал бы, что простое решение будет состоять в том, чтобы перенести объект и делегировать, содержит вызов к набору перенесенного класса. Это подобно компаратору, но не вынуждает Вас отсортировать получающийся набор, можно просто использовать ArrayList.contains ().

public class Widget {
        private String name;
        private String desc;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getDesc() {
            return desc;
        }

        public void setDesc(String desc) {
            this.desc = desc;
        }
    }



    public abstract class EqualsHashcodeEnforcer<T> {

        protected T wrapped;

        public T getWrappedObject() {
            return wrapped;
        }

        @Override
        public boolean equals(Object obj) {
            return equalsDelegate(obj);
        }

        @Override
        public int hashCode() {
            return hashCodeDelegate();
        }

        protected abstract boolean equalsDelegate(Object obj);

        protected abstract int hashCodeDelegate();
    }


    public class WrappedWidget extends EqualsHashcodeEnforcer<Widget> {

        @Override
        protected boolean equalsDelegate(Object obj) {
            if (obj == null) {
                return false;
            }
            if (obj == getWrappedObject()) {
                return true;
            }
            if (obj.getClass() != getWrappedObject().getClass()) {
                return false;
            }
            Widget rhs = (Widget) obj;

            return new EqualsBuilder().append(getWrappedObject().getName(),
                    rhs.getName()).append(getWrappedObject().getDesc(),
                    rhs.getDesc()).isEquals();
        }

        @Override
        protected int hashCodeDelegate() {

            return new HashCodeBuilder(121, 991).append(
                    getWrappedObject().getName()).append(
                    getWrappedObject().getDesc()).toHashCode();
        }

    }
0
ответ дан jonathan.cone 7 November 2019 в 08:48
поделиться

Существует три основных опции:

1), Если выполнение извлечения является главным и это практично, чтобы сделать так, использовать форму хеш-таблицы, созданной однажды (и измененный, когда Список изменяется).

2), Если Список удобно отсортирован или это практично для сортировки его, и O (зарегистрируйте n), извлечение достаточно, вид и поиск.

3), Если O (n) извлечение достаточно быстр или если это невозможно управлять/поддерживать структурой данных или альтернативой, выполните итерации по Списку.

Перед написанием кода, более сложным, чем простое повторение по Списку, стоит продумать некоторые вопросы.

  • , Почему что-то другое необходимо? (Время) производительность? Элегантность? Пригодность для обслуживания? Повторное использование? Все они являются хорошо причинами, независимо или вместе, но они влияют на решение.

  • , Сколько контроля Вы имеете над рассматриваемой структурой данных? Можно ли влиять, как это создается? Управляемый позже?

  • , Каков жизненный цикл структуры данных (и основные объекты)? Это создается внезапно и никогда не изменяется или очень динамичное? Ваш код может контролировать (или даже измениться), его жизненный цикл?

  • там другие важные ограничения, такие как объем потребляемой памяти? Информация о вопросе дубликатов? И т.д.

1
ответ дан Jeremy Rishel 7 November 2019 в 08:48
поделиться

Если необходимо искать многих время в том же списке, он может окупиться для создания индекса.

Выполняют итерации однажды через и создают HashMap с, равняется значению, которое Вы ищете как ключ и соответствующий узел как значение. Если Вам нужно, все вместо любого из данного равняются значению, то позволенный карта иметь тип значения списка и создает целый список в начальном повторении.

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

1
ответ дан Thorbjørn Ravn Andersen 7 November 2019 в 08:48
поделиться

Возможно, Список не то, в чем Вы нуждаетесь.

, Возможно, TreeSet был бы лучшим контейнером. Вы добираетесь, O (зарегистрируйте N), вставка и извлечение и заказанное повторение (но не позволит дубликаты).

LinkedHashMap мог бы быть еще лучше для Вашего варианта использования, проверить это также.

2
ответ дан Ben Hardy 7 November 2019 в 08:48
поделиться

там какой-либо лучший путь, чем просто цикличное выполнение через и вручную сравнение этих двух полей для каждого объекта и затем повреждения при нахождении? Это просто кажется настолько грязным, ища лучший путь.

, Если Ваше беспокойство является пригодностью для обслуживания, Вы могли бы сделать то, что Fabian Steeg предлагает (это - то, что я сделал бы), хотя это, вероятно, не является "самым эффективным" (потому что необходимо отсортировать массив сначала и затем выполнить двоичный поиск), но конечно самый чистый и более оптимальный вариант.

, Если Вы действительно обеспокоены эффективностью, можно создать пользовательскую Реализацию списка, которая использует поле в объекте как хеш, и используйте HashMap в качестве устройства хранения данных. Но вероятно это было бы слишком много.

Затем необходимо изменить место, где Вы заполняете данные от ArrayList до YourCustomList.

Как:

 List list = new ArrayList();

 fillFromSoap( list );

К:

 List list = new MyCustomSpecialList();

 fillFromSoap( list );

реализация была бы чем-то как следующее:

class MyCustomSpecialList extends AbstractList  { 
    private Map<Integer, YourObject> internalMap;

    public boolean add( YourObject o ) { 
         internalMap.put( o.getThatFieldYouKnow(), o );
    }

    public boolean contains( YourObject o ) { 
        return internalMap.containsKey( o.getThatFieldYouKnow() );
    }

}

В значительной степени как HashSet, проблемой здесь является HashSet, полагается на хорошую реализацию метода хэш-кода, который, вероятно, Вы не имеете. Вместо этого Вы используете в качестве хеша, "которому поле, которое Вы знаете", который является тем, который делает один объект, равняется другому.

, Конечно, реализация Списка от партии царапины, более хитрой, чем мой отрывок выше, вот почему, я говорю Fabian Steeg , предложение было бы лучше и легче реализовать (хотя что-то вроде этого будет более эффективным)

, Говорят нам, что Вы сделали в конце.

2
ответ дан Community 7 November 2019 в 08:48
поделиться

Создание HashMap этих объектов на основе значения поля как ключ могло стоить с точки зрения производительности, например, заполнить Карты однажды и найти объекты очень эффективно

1
ответ дан Rocket Surgeon 7 November 2019 в 08:48
поделиться

Даже если бы равняется методу , были сравнение тех двух полей, то логически, это был бы просто тот же код как Вы делающий его вручную. Хорошо, это могло бы быть "грязно", но это - все еще корректный ответ

4
ответ дан oxbow_lakes 7 November 2019 в 08:48
поделиться

Если список , отсортировал , можно использовать двоичный поиск . В противном случае затем нет никакого лучшего пути.

при выполнении этого много это почти наверняка стоило бы Вашего, в то время как отсортировать список в первый раз. Так как Вы не можете изменить классы, необходимо было бы использовать Comparator , чтобы сделать сортировку и поиск.

6
ответ дан Bombe 7 November 2019 в 08:48
поделиться

Учитывая Ваши ограничения, Вы застреваете с поиском грубой силы (или создание индекса, если поиск будет повторен). Можно ли разработать кого-либо о том, как эти ArrayList сгенерирован - возможно, там существует некоторое пространство для маневра.

, Если все Вы ищете, более симпатичный код, рассмотрите использование Apache классы Наборов палаты общин, в особенности CollectionUtils.find () , для готового синтаксического сахара:

ArrayList haystack = // ...
final Object needleField1 = // ...
final Object needleField2 = // ...

Object found = CollectionUtils.find(haystack, new Predicate() {
   public boolean evaluate(Object input) {
      return needleField1.equals(input.field1) && 
             needleField2.equals(input.field2);
   }
});
10
ответ дан Michael Brewer-Davis 7 November 2019 в 08:48
поделиться

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

class Thing { String a, b, c, d; }

Вы определили бы свой Компаратор:

Comparator<Thing> comparator = new Comparator<Thing>() {
  public int compare(Thing o1, Thing o2) {
    if (o1.a.equals(o2.a)) {
      return o1.b.compareTo(o2.b);
    }
    return o1.a.compareTo(o2.a);
  }
};

Затем сортируют Ваш список:

Collections.sort(list, comparator);

И наконец делают двоичный поиск:

int i = Collections.binarySearch(list, thingToFind, comparator);
37
ответ дан Fabian Steeg 7 November 2019 в 08:48
поделиться

Если Вы - пользователь моего ForEach DSL, он может быть сделан с Detect запрос.

Foo foo = ...
Detect<Foo> query = Detect.from(list);
for (Detect<Foo> each: query) 
    each.yield = each.element.a == foo.a && each.element.b == foo.b;
return query.result();
4
ответ дан akuhn 7 November 2019 в 08:48
поделиться
Другие вопросы по тегам:

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