2016-07-13 3 views
0

Я ищу наиболее эффективный способ получить все элементы от List<String>, которые содержат значение String ("value1").JAVA эффективный способ чтения журналов из файла

Первая мысль - простая итерация и добавление элементов, содержащих "value1", другому List<String> Но эта задача должна выполняться очень часто и многими пользователями.

Мысль о list.RemoveAll(), но как удалить все элементы, которые не содержат "value1"?

Итак, каким образом это сделать наиболее эффективно?

UPDATE:

Вся картина - нужно нужно читать журналы из файла очень часто и для нескольких пользователей одновременно. Журналы должны быть отфильтрованы по имени пользователя из файла. каждая строка в файле содержит имя пользователя.

+1

Является ли обычный способ слишком медленным для вас? ... – Idos

+1

1) Зачем беспокоиться? Это может быть случай преждевременной оптимизации, поэтому, пожалуйста, будьте более конкретными. 2) Строки просто должны _содерживать_ значение или они _equal_ к значению, т. Е. Должно быть «Привет, строка String1». удалить? – Thomas

+0

, если он должен быть «равным», я бы так сказал. они должны 'содержать' значение – user1935987

ответ

1

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

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

Однако, в зависимости от вашего варианта использования, это может не стоить усилий, и вы можете просто пойти и отфильтровать список всякий раз, когда пользователь попросит об этом. В этом случае я рекомендую читать файл по строкам и добавлять только соответствующие строки в список. Если вы сначала прочитали все в один список и затем удалили несоответствующие элементы, он будет менее эффективен (вам придется чаще итерации, смены элементов и т. Д.) И временно использовать больше памяти (в противоположность отбрасыванию каждого не- соответствующая линия сразу после проверки).

+0

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

0

Вместо List, используйте TreeSet с предоставленным Comparator, чтобы все строки с «значением1» находились в начале. При повторении, как только строка не содержит «value1», все остальные не имеют ее, и вы можете остановить ее итерацию.

0

Итерация, вероятно, единственный способ, но вы можете позволить Java оптимизировать его как можно больше (и использовать элегантный, номера императивный синтаксис) с использованием Java-8 в потоки:

// test list 
List<String> original = new ArrayList<String>(){ 
    { 
     add("value1");add("foo");add("foovalue1");add("value1foo"); 
    } 
}; 
List<String> trimmed = original 
    .stream() 
    .filter((s) -> s.contains("value1")) 
    .collect(Collectors.toList()); 
System.out.println(trimmed); 

Выходные

[value1, foovalue1, value1foo] 

Примечания

  • Одна часть вашего вопроса, которая может потребовать дополнительной информации, «часто выполняется многими пользователями» - это может вызвать некоторый механизм обработки параллелизма.
  • Фактическая функциональность не очень ясна. Вы все еще можете иметь пространство для оптимизации кода рано извлекая и собирая "value1" отработанный String s до строительства вы List
+0

Я получаю список , читая файл в нем – user1935987

+0

@ user1935987 ну вот и все. Если вам нужен только '' value1 "' -содержащий 'String' из этого файла, вы можете работать с вашим механизмом де-сериализации путем предварительной фильтрации содержимого (** edit **: подробности этой реализации лучше подходят новый вопрос, если это потребуется). – Mena

+0

Выполняется только чтение из файла. поэтому я не думаю, что будут проблемы с параллелизмом – user1935987

0

Хорошо, в этом я могу предложить вам самый простой, я использовал. Использование итератора, делает его легче, но если вы идете с list.remove (VAL), Допустимы = "значение1", может дать вам UnsupportedOperationException

список List = yourList;/содержит "value1"/

for (Iterator<String> itr = list.iterator(); itr.hasNext();){ 
String val = itr.next(); 
if(!val.equals("value1")){ 

    itr.remove(); 

} 


} 

Попробуйте это и дайте мне знать. :)

+0

, почему это сделано как не полезное? –

+0

Просто код публикации без каких-либо объяснений считается плохим. И «попробуй это» на самом деле не объяснение. Кроме того: ленивое форматирование. Форматирование на самом деле не так уж и плохо, но это совершенно очевидно, что вы действительно только сделали необходимый минимум здесь. – GhostCat

2

С точки зрения эффективности времени вы не можете получить лучший результат, чем линейный (O(n)), если хотите выполнить итерацию по всему списку.

Решение между LinkedList и ArrayList и т. Д., Скорее всего, не имеет значения, поскольку различия невелики.

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

  • , если вы заранее знаете, что строка, которую вы будете искать, вы можете создать еще один список по с вашим первоначальный список, содержащий только соответствующие записи
  • , если вы знаете, что вы собираетесь запросить один список несколько раз, можно построить индекс

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

Смежные вопросы