The list of rows gets an element starting without a loop

I have a list of arrays containing thousands of data.

Example:

List<String> custNames = new ArrayList<String>(); custNames.add("John"); custNames.add("Tom"); custNames.add("Bart"); custNames.add("Tim"); custNames.add("Broad"); 

Now I want to get the number of names, just starting with 'T'. I used the loop mechanism for my solution.

 List<String> filterNames = new ArrayList<String>(); String nameStarts="T"; for(int i=0;i<custNames.size();i++) { if(custNames.get(i).toLowerCase().startsWith(nameStarts.toLowerCase())) { filterNames.add(custNames.get(i)); } } System.out.println(filterNames.size()); 

But I have a very large dataset in this custNames list. Is there any other solution without using a loop?

Thanks.

+5
source share
8 answers

There is a very good solution from Java 8 for your problem.

Try it,

 long filterNameCount = custNames .stream() .parallel() .filter((s) -> s.startsWith(nameStarts.toLowerCase())) .count(); System.out.println(filterNameCount); 
+5
source

If you are open to using a third-party library, there are some interesting options that you could use with Eclipse Collections .

If you are using an ArrayList as described above, you can use the LazyIterate utility as follows:

 int count = LazyIterate.collect(custNames, String::toLowerCase) .countWith(String::startsWith, nameStarts.toLowerCase()); Assert.assertEquals(2, count); 

If you use the Eclipse collection replacement for ArrayList , you can use the rich functional protocols available directly on the MutableList :

 MutableList<String> custNames = Lists.mutable.with("John", "Tom", "Bart", "Tim", "Broad"); String nameStarts= "T"; int count = custNames.asLazy() .collect(String::toLowerCase) .countWith(String::startsWith, nameStarts.toLowerCase()); System.out.println(count); Assert.assertEquals(2, count); 

The serial API in Eclipse collections compiles by default, so I called asLazy() first. A collection method would otherwise create another MutableList .

If you are comparing your code with a complete set of data, the following parallel version of the code may be more efficient:

 MutableList<String> custNames = Lists.mutable.with("John", "Tom", "Bart", "Tim", "Broad"); String nameStarts= "T"; int processors = Runtime.getRuntime().availableProcessors(); int batchSize = Math.max(1, custNames.size() / processors); ExecutorService executor = Executors.newFixedThreadPool(processors); int count = custNames.asParallel(executor, batchSize) .collect(String::toLowerCase) .countWith(String::startsWith, nameStarts.toLowerCase()); executor.shutdown(); Assert.assertEquals(2, count); 

The asParallel() API in Eclipse collections is the default. The API forces you to pass in the format ExecutorService and int batchSize. This gives you full control over parallelism.

You can also use the Stream API with all MutableCollections in Eclipse collections, because they extend java.util.Collection .

Note. I am a committer for Eclipse collections.

+3
source

You can also use tree storage: it would be very effective for such a search. If you are stuck on a list, then the previous answer is a way to do it.

0
source

If you have a more or less static list and you often perform a search operation, you can sort your list or use TreeMap.

Also you do not need to create a new list and then get its size. You can simply create a counter variable and increment it.

0
source

delete all elements that do not start with "T" as follows:

 custNames.removeIf(p->!p.startsWith("T")); 

you can make a copy from your list and remove items that do not begin with "T".

0
source

First, you can shorten your initialization with Arrays.asList(T) ; Secondly, I would use a simple loop to build the counting table once , and then use it to determine subsequent queries. Sort of,

 List<String> custNames = new ArrayList<String>(Arrays.asList("John", "Tom", "Bart", "Tim", "Broad")); int[] counts = new int[26]; for (String name : custNames) { char ch = Character.toLowerCase(name.charAt(0)); counts[ch - 'a']++; } for (int i = 0; i < counts.length; i++) { if (counts[i] > 0) { System.out.printf("There are %d words that start with %c%n", counts[i], (char) ('a' + i)); } } 

What are the exits

 There are 2 words that start with b There are 1 words that start with j There are 2 words that start with t 

Or, in a particular case, counts['t' - 'a'] is the number of words starting with t .

0
source

If the order in which the elements are stored does not matter, you can save the names in a HashMap, where the first character of each name is the key, and the ArrayList of names with this first character is the value. And then all you have to do if the HashMap is called customerList is customerList.get ("T"). Size ().

Initializing a HashList and Adding Clients

 HashMap<Character, ArrayList<String>> customerList = new HashMap<Character, ArrayList<String>>(); int NUM_ALPHABETS = 26; int ascii_char = 97; for(int i = 0; i < NUM_ALPHABETS; i++){ char c = (char) ascii_char; customerList.add(c, new ArrayList<String>()); ascii_char++; } customerList.get("t").add("Tony"); customerList.get("a").add("Alice"); customerList.get("b").add("Ben"); 

Getting the number of customers Starting with "t"

  int num_t = customerList.get("t").size(); 
0
source

You can create your own sorting and searching procedure.

Consider the following:

 public class ContainingArrayList<E> extends ArrayList<E> { private Comparator<E> comparator; public ContainingArrayList(Comparator<E> comparator) { this.setComparator(comparator); } @Override public boolean add(E e) { // If the collection is empty or the new element is bigger than the last one, append it to the end of the collection if(size() == 0 || comparator.compare(e, get(size()-1)) >= 0) return super.add(e); else { for (int i = 0; i < size(); i++) { int result = comparator.compare(e, get(i)); // If the new element is bigger than the current element, continue with the next element if (result > 0) continue; // If the new element is equal to the current element, no need to insert (you might insert of course) if (result == 0) return false; // Otherwise the new element is smaller than the current element, so insert it between the previous and the current element super.add(i, e); return true; } return super.add(e); } } public E get(E containingElement) { int start = 0; int end = size()-1; // If the element is the first one, return the first element if(comparator.compare(containingElement, super.get(start)) == 0) return super.get(start); // If the element is the last one, return the last element if(comparator.compare(containingElement, super.get(end)) == 0) return super.get(end); // Otherwise do a binary search while(start != end) { // Get the element between start and end positions E mid = super.get(start + (end/2)); // Compare the two elements int result = comparator.compare(containingElement, mid); // If the middle element compared to the containing element is equal, return the middle element if(result == 0) { return mid; } // If the containing element is smaller than the middle, halve the end position else if(result < 0) { end = start + (end/2); } // If the containing element is bigger than the middle, set the start position to the middle position else if(result > 0) { start = start + (end/2); } } return null; } public Comparator<E> getComparator() { return comparator; } public void setComparator(Comparator<E> comparator) { this.comparator = comparator; } } 

A custom comparator is used to sort items and find an item that starts with a specific character. This means that you can change the comparator implementation for your needs at any time or create a more dynamic search solution.

Test:

 public class SortFindTest { public SortFindTest() { ContainingArrayList<String> t = new ContainingArrayList<String>(new MyComparator()); t.add("John"); t.add("Tom"); t.add("Bart"); t.add("Tim"); t.add("Broad"); System.out.println(t.get("T")); } class MyComparator implements Comparator<String> { @Override public int compare(String o1, String o2) { int o1c = o1.charAt(0); int o2c = o2.charAt(0); if(o1c == o2c) return 0; if(o1c > o2c) return 1; return -1; } } public static void main(String[] args) { new SortFindTest(); } } 

I'm not sure if this will be faster than the Java 8 Stream API, but worth a try.

0
source

Source: https://habr.com/ru/post/1258255/


All Articles