3

I am having a java ArrayList of integer

ArrayList <Integer> ageList  = new ArrayList <Integer>();

I am having some integer values in this arrayList. I want to create a new ArrayList which has all elements in the above arrayList which passes a condition, like value between 25 and 35. ie if my ageList contains values

{12,234,45,33,28,56,27}

my newList should contain

{33,28,27}

How can I achieve this?

Note: I came to java from objective C background, where I used NSPredicate to easly do such kind of things..Any similiar methods in java?

Krishnabhadra
  • 34,169
  • 30
  • 118
  • 167
  • Just going over the list in a loop won't do? – ZenMaster Sep 14 '11 at 10:09
  • Surely it will do, but I am already a loop of around 100 iteration, and I have to do the above inside that loop..Also I am asking for a faster way – Krishnabhadra Sep 14 '11 at 10:12
  • 3
    I think you're making a big assumption; the ObjectiveC implementation will also loop over it, just you won't see the loop as it is masked by a feature. The underlying implementation of NSPredicate will still have to loop over the array to assess each element. – Charles Goodwin Sep 14 '11 at 10:15
  • I just hope that you are aware that with the toolkits mentioned below (specifically lambdaj) there is a performance hit relative to just iterating over... from what I know, at least. – ZenMaster Sep 14 '11 at 10:26
  • Down voter please care to comment, so that I can understand what I did wrong.. – Krishnabhadra Sep 30 '11 at 05:48

7 Answers7

7

There is no "filter" facility in the standard API. (There is in Guava and Apache Commons however.) You'll have to create a new list, loop through the original list and manually add the elements in range 25-35 to the new list.

If you have no intention to keep the original list, you could remove the elements out of range using an Iterator and the Iterator.remove method.

If you have no duplicates in your list, you could use a TreeSet in which case you could get all elements in a specific range using headSet / tailSet.

Related question: (possibly even a duplicate actually)

Community
  • 1
  • 1
aioobe
  • 413,195
  • 112
  • 811
  • 826
  • I wish there was a variant of the `foreach` loop that supported remove. – Thilo Sep 14 '11 at 10:18
  • Well I saw that thread..And tried its implementation..I am one month into java, and I am understanding java as a pretty highlevel language..So I thought there should be some kind of pretty straightforward method..Also I am writing for Android, which is after all an embedded device, and one less line of code (especially in a loop) will do no harm..Anyway if I have to loop, I am ready to loop...Thanks for the effort.. – Krishnabhadra Sep 14 '11 at 10:22
  • 1
    Well I decided to loop around atlast..Dont want to add external libraries just for this case, even if it is by mighty Google..Thanks for the response..I am going to have a loooooooooooooooop...... – Krishnabhadra Sep 14 '11 at 10:41
  • you can also explore Navigable Set (unique values) and Navigable Map (key as unqiues values, value as count of duplicates) and then do headset, heapMap, tailSet, tailMap et-all – Scorpion Sep 14 '11 at 11:13
6

Well, with Guava you could write:

Iterable<Integer> filtered = Iterables.filter(list, new Predicate<Integer>() {
    @Override public boolean apply(Integer value) {
        return value >= 25 && value <= 35;
    }
});
List<Integer> newList = Lists.newArrayList(filtered);
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    +1, nice. I usually write such ranges as `25 <= value && value <= 35` to mimic the mathematical notation `25 <= value <= 35`. – aioobe Sep 14 '11 at 10:11
  • 1
    @aioobe: I appreciate that approach, but equally I find conditions with the constant on the left harder to understand. There's an argument for a range type in there somewhere :) – Jon Skeet Sep 14 '11 at 10:14
  • +1, if you can trust Guava doesn't phone home with each iteration. XD – Mister Smith Sep 14 '11 at 10:29
  • Thanks for this, I never heard of Guava before, but I am only starting in java..For the present problem I decided to stick with a Iterator and loop..I am sure I will come back to guava sometime in future.. – Krishnabhadra Sep 14 '11 at 10:44
6

You may use foreach loop

List<Integer> newList = new ArrayList<Integer>();
for (Integer value : ageList) {
    if (value >= 25 && value <= 35) {
        newList.add(value);
    }
}
user219882
  • 15,274
  • 23
  • 93
  • 138
4

Try this:

ArrayList<Integer> newList = new ArrayList<Integer>(ageList);
for (Iterator<Integer> it = newList.iterator(); it.hasNext();) {
    int n = it.next();
    if (n < 25 || n > 35)
      it.remove();
}
z3pr4h
  • 196
  • 4
1

No there is no built in functionality in java [AFAIK].

The steps can be:

  1. Loop through ageList.
  2. Check for condition.
  3. If condition is success then add that element to new list or else do nothing.

Sample code:

    List<Integer> ageList = new ArrayList<Integer>();
    //-- add data in ageList

    List<Integer> newList = new ArrayList<Integer>();
    for (Integer integer : ageList) {
        if(integer >= 25 && integer <= 35)
            newList.add(integer);
    }
Harry Joy
  • 58,650
  • 30
  • 162
  • 207
1

Not possible with the standard JCF. You'll have to iterate.

Consider using Guava. It has such kind of utilities.

http://code.google.com/p/guava-libraries/

Mister Smith
  • 27,417
  • 21
  • 110
  • 193
0

Iterate over it and just add the ones that match? It's 3 lines of code... 4 including the new ArrayList declration.

Charles Goodwin
  • 6,402
  • 3
  • 34
  • 63