user1935987
user1935987

Reputation: 3347

JAVA the efficient way to read a logs from file

I'm looking for most effective way to get all the elements from List<String> which contain some String value ("value1") for example.

First thought - simple iteration and adding the elements which contains "value1" to another List<String> But this task must be done very often and by many users.

Thought about list.RemoveAll(), but how do I remove all elements which don't contain "value1"?

So, what is the way to make it most efficiently?

UPDATE:

The whole picture - need to need to read the logs from file very often and for multiple users simultaneously. The logs must be filtered by the username from file. each string in file contains username.

Upvotes: 0

Views: 110

Answers (5)

Thomas
Thomas

Reputation: 88727

From your comments it seems like your list is a couple of log statements that should be grouped by user id (which would be your "value1"). If you really need to read the logs very often and for multiple users simultaneously you might consider some caching, possibly with grouping by user id.

As an example you could maintain an additional log file per user and just display it when needed. Alterantively you could keep the latest log statements in memory by employing some FIFO buffer which is grouped by user id (could be a buffer per user and maybe another LIFO layer on top of that).

However, depending on your use case it might not be worth the effort and you might just go and filter the list whenever the user requests to do so. In that case I'd recommend reading the file line by line and only adding the matching lines to the list. If you first read everything into a single list and then remove non-matching elements it'll be less efficient (you'd have to iterate more often, shift elements etc.) and temporarily use more memory (as opposed by discarding every non-matching line right after checking it).

Upvotes: 1

Surajit Biswas
Surajit Biswas

Reputation: 809

Ok, in this I can suggest you the simplest one, I had used. Use of an Iterator, makes it easier but if you go with list.remove(val) , where val = "value1" , may give you UnsupportedOperationException

List list = yourList; /contains "value1"/

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

    itr.remove();

}


}

Try this one and let me know. :)

Upvotes: 0

Jiri Tousek
Jiri Tousek

Reputation: 12440

In terms of time efficiency, you cannot get to better result than linear (O(n)) if you want to iterate through the whole list.

Deciding between LinkedList and ArrayList etc. is most likely irrelevant as the differences are small.

If you want a better time than linear to list size, you need to build on some assumptions and prerequisites:

  • if you know beforehand what string you'll search for, you can build another list along with your original list containing only relevant records
  • if you know you're going to query one list multiple times, you could build an index

If you just have a list on input that someone gave you, and you need to read through this one input once and find the relevant strings, then you're stuck with linear time since you cannot avoid reading the list at least once.

Upvotes: 2

Mena
Mena

Reputation: 48404

The iteration is likely the only way, but you can allow Java to optimize it as much as possible (and use an elegant, non imperative syntax) by employing Java 8's streams:

// 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);

Output

[value1, foovalue1, value1foo]

Notes

  • One part of your question that may require more information is "performed often, by many users" - this may call for some concurrency-handling mechanism.
  • The actual functionality is not very clear. You may still have room to optimize your code early by fetching and collecting the "value1"-containing Strings prior to building you List

Upvotes: 0

jan.supol
jan.supol

Reputation: 2805

Instead of List, Use TreeSet with provided Comparator so that all Strings with "value1" are at the beginning. When iterating, as soon as the string does not contain "value1", all the remaining do not have it, and you can stop to iterate.

Upvotes: 0

Related Questions