I have a array list contains thousands of data.
For 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 count of names only starting with 'T'. I used looping 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 very large collection of data in this custNames list. Is there any different solution without using loop?
Thanks.
There is very good solution from Java 8 for your problem.
Try this,
long filterNameCount = custNames
.stream()
.parallel()
.filter((s) -> s.startsWith(nameStarts.toLowerCase()))
.count();
System.out.println(filterNameCount);
If you are open to using a third-party library, there are a few interesting options you could use with Eclipse Collections.
If you use the ArrayList
as you have it 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 Collections replacement for ArrayList
, you can use the rich functional protocols available directly on 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 is eager-by-default, which is why I called asLazy()
first. The collect method would otherwise create another MutableList
.
If you benchmark your code with your full set of data, the following parallel version of the code may be more performant:
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 lazy-by-default. The API forces you to pass in a an ExecutorService
and an int
batchSize. This gives you complete control over the 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With