Is there a construct in java that does something like this(here implemented in python):
[] = [item for item in oldList if item.getInt() > 5]
Today I'm using something like:
ItemType newList = new ArrayList();
for( ItemType item : oldList ) {
if( item.getInt > 5) {
newList.add(item);
}
}
And to me the first way looks a bit smarter.
Java 7 might or might not implement closures and hence support functionality like this, but currently it doesn't, so on the Java VM you have the options to do it in Groovy, Scala or Clojure (possible others, too), but in java you can only get close to that by using helpers like Guava's Collections2.filter().
JDK 7 sample code:
findItemsLargerThan(List<Integer> l, int what){
return filter(boolean(Integer x) { x > what }, l);
}
findItemsLargerThan(Arrays.asList(1,2,5,6,9), 5)
Groovy sample code:
Arrays.asList(1,2,5,6,9).findAll{ it > 5}
Guava Sample Code:
Collections2.filter(Arrays.asList(1, 2, 5, 6, 9),
new Predicate<Integer>(){
#Override
public boolean apply(final Integer input){
return input.intValue() > 5;
}
}
);
Scala sample code (thanks Bolo):
Array(1, 2, 5, 6, 9) filter (x => x > 5)
You can give a look at lambdaj. There is a select method you can use with a hamcrest condition.
Nothing is impossible (-:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ListCleaner {
public static void main(String[] args) {
final List<Integer> oldList = Arrays.asList(new Integer[] { 23, 4, 5,
657 });
System.out.println(oldList);
List<Integer> newList = new ArrayList<Integer>() {
{
for (Integer element : oldList) {
if (element > 5) {
this.add(element);
}
}
}
};
System.out.println(newList);
}
}
The only constraint is that the oldList has to be final.
It can be done in pure Java, but you need to write a support class Filter for the following code to run successfully:
List<Integer> oldList = Arrays.asList(new Integer[] { 1, 2, 5, 6, 9 });
List<Integer> newList = new Filter<Integer>(oldList) {
{
findAll(it > 5);
}
}.values();
System.out.println(newList); // [6, 9]
In case you wonder why this code compiles take a look at Hidden features of Java: Double brace initialization. This creates an anonymous instance of the class Filter that contains the it variable and provides the method findAll().
The Filter class itself has the one drawback that a new instance is created for each list element to evaluate the boolean condition at findAll():
public abstract class Filter<T> {
protected List<T> values = new ArrayList<T>();
protected T it;
public Filter(List<T> values) {
if (values != null) {
this.values.addAll(values);
}
if (values.isEmpty()) {
throw new RuntimeException("Not for empty collections!");
}
it = values.iterator().next();
// instance initializer gets executed here, calls findAll
}
protected void findAll(boolean b) throws Throwable {
// exit condition for future calls
if (values.size() > 1) {
// only repeat for each entry, if values has multiple entries
Iterator<T> iterator = values.iterator();
while (iterator.hasNext()) {
// don't evalute again for the first entry
if (!b) {
iterator.next();
iterator.remove();
b = true;
} else {
// for each other entry create an argument with one element
List<T> next = new ArrayList<T>();
next.add(iterator.next());
// get constructor of anonymous class
Constructor<?> constructor = this.getClass().getDeclaredConstructors()[0];
// invoke constructor and thus execute instance initializer again
Filter<T> filtered = (Filter<T>) constructor.newInstance(new Object[] { null, next });
// if values is empty, the condition didn't match and the element can be removed
if (filtered.values.isEmpty()) {
iterator.remove();
}
}
}
} else {
// one element can be checked directly
if (!b) {
values.clear();
}
}
}
public List<T> values() {
return values;
}
}
But as instance creation is rather cheap these days and the Filter class is usable for all Objects, it may be worth including in your Utils package.
Greetz,
GHad
No, this kind of dynamic language construct is not supported in Java yet :-) So you have to live with your option 2
Related
In Java docs it is given -
Modifier and Type Method and Description
static <T> Predicate<T> isEqual(Object targetRef)
Returns a predicate that tests if two arguments are equal according to Objects.equals(Object, Object).
In https://www.geeksforgeeks.org/java-8-predicate-with-examples/
it is given -
isEqual(Object targetRef) : Returns a predicate that tests if two arguments are equal according to Objects.equals(Object, Object).
static Predicate isEqual(Object targetRef)
Returns a predicate that tests if two arguments are
equal according to Objects.equals(Object, Object).
T : the type of arguments to the predicate
Parameters:
targetRef : the object reference with which to
compare for equality, which may be null
Returns: a predicate that tests if two arguments
are equal according to Objects.equals(Object, Object)
I can't get a grisp of what this Objects.equals(Object, Object) might be
I write the following code to try it out -
Class Fruits -
Fruits.java -
public class Fruits {
private String fruit;
public Fruits(String fruit) {
this.fruit = fruit;
}
public String getFruit() {
return fruit;
}
}
Here, the other methods of predicate seem to be quite easy to understand -
Predicate<List<Fruits>> containsApple = list -> {
boolean myReturn = false;
Iterator<Fruits> iterator = list.iterator();
while (iterator.hasNext()) {
Fruits fruits = iterator.next();
String fruit = fruits.getFruit();
if (fruit.equals("Apple")) {
myReturn = true;
break;
}
}
return myReturn;
};
Predicate<List<Fruits>> containsOrange = list -> {
boolean myReturn = false;
Iterator<Fruits> iterator = list.iterator();
while (iterator.hasNext()) {
Fruits fruits = iterator.next();
String fruit = fruits.getFruit();
if (fruit.equals("Orange")) {
myReturn = true;
break;
}
}
return myReturn;
};
Predicate<List<Fruits>> containsAppleAndOrange = list -> {
return containsApple.and(containsOrange).test(list);
};
Predicate<List<Fruits>> containsAppleOrRange = list -> {
return containsApple.or(containsOrange).test(list);
};
Predicate<List<Fruits>> notContainsApple = list -> {
return containsApple.negate().test(list);
};
Predicate<List<Fruits>> notContainsOrange = list -> {
return containsOrange.negate().test(list);
};
Predicate<List<Fruits>> notContainsAppleAndOrange = list -> {
return containsAppleAndOrange.negate().test(list);
};
Predicate<List<Fruits>> notContainsAppleOrOrange = list -> {
return containsAppleOrRange.negate().test(list);
};
Here I test it with following data -
List<Fruits> list1 = new ArrayList<>(List.of(
new Fruits("Apple"),
new Fruits("Orange"),
new Fruits("Mango"),
new Fruits("Banana")
));
List<Fruits> list2 = new ArrayList<>(List.of(
new Fruits("Apple"),
new Fruits("Mango"),
new Fruits("Banana"),
new Fruits("Berry")
));
List<Fruits> list3 = new ArrayList<>(List.of(
new Fruits("Orange"),
new Fruits("Mango"),
new Fruits("Banana"),
new Fruits("Berry")
));
Result is as expected.
But in no way can I understand how to implement the isEqual() method -
To see that two arguments are equal are not I create another predicate -
redicate<List<Fruits>> containsApple2 = list -> {
boolean myReturn = false;
Iterator<Fruits> iterator = list.iterator();
while (iterator.hasNext()) {
Fruits fruits = iterator.next();
String fruit = fruits.getFruit();
if (fruit.equals("Apple")) {
myReturn = true;
break;
}
}
return myReturn;
};
I try something like (without understanding why) -
System.out.println(Predicate.isEqual(containsApple).test(list1));
Output - false
Now what happened here?
System.out.println(Predicate.isEqual(containsApple2).test(containsApple));
Output - false
Now again what happened here?
So, how to exactly use this isEqual method?
Predicate.isEqual is a factory method that creates predicates that test if a given thing is equal to the parameter passed in.
Predicate.isEqual(containsApple) creates a Predicate<Predicate<List<Fruits>>> that tests if a given thing is equal to containsApple. However, since containsApple refers to an instance created from a lambda, and nothing much is guaranteed about the equality of instances created from lambda expressions (See the JLS), nothing much can be said about the result of calling test on it. The classes of the lambda instances may or may not implement equals, and containsApple may or may not be the same instance as containsApple2, depending on the implementation.
Rather than comparing lambda instances, a typical example of using Predicate.isEqual is:
Fruits apple = new Fruits("Apple");
Predicate<Fruits> isApple = Predicate.isEqual(apple);
// rather than this slightly longer version:
// Predicate<Fruits> isApple = x -> Objects.equals(x, apple);
Then you can pass isApple around, to other methods that take Predicates, and/or call test on it. isApple.test(apple) would be true, isApple.test(new Fruits("something else")) would be false. I would also recommend that you override equals and hashCode in Fruits.
Note that we generally make predicates that test against individual objects, rather than lists (collections) of things. We would pass these predicates to other methods (such as Stream.filter), and let them do the filtering. For example, to filter a list to get all the apples:
List<Fruits> apples = fruitsList.stream()
.filter(Predicate.isEqual(apple)).toList();
One should use singular here for the class Fruits.
First you must establish equality of Fruit. Also should you ever want it to store in a HashMap or HashSet, a hashCode implementation is important.
public class Fruit {
private final String fruit; // Or name.
public Fruit(String fruit) {
this.fruit = fruit;
}
public String getFruit() {
return fruit;
}
#Override
public boolean equals(Object other) {
return other instanceOf Fruit && ((Fruit) other).fruit.equals(fruit);
}
#Override
public int hashCode() {
return fruit.hashCode();
}
}
The Iterator class is rather old and its primary advantage is you can walk through and still remove an element with iterator.remove(), which is not allowed on the List in a - statefull - for (ConcurrentModificationException).
Predicate<List<Fruit>> containsApple = list -> {
for (Fruit fruit: list) {
if (fruit.getFruit().equals("Apple")) {
return true;
}
}
return false;
};
Predicate<List<Fruit>> containsApple = list -> list.contains(new Fruit("Apple"));
Advisable is to get acquainted with Stream (like for iterating through a collection) and its expressive power.
Predicate<List<Fruit>> containsApple = list ->
list.stream()
.anyMatch(fr -> fr.getFruit().equals("Apple"));
As mentioned by #user16320675 in comments one of the simplest examples would be -
import java.util.function.Predicate;
public class App {
public static void main(String[] args) {
Integer num1 = 2;
Integer num2 = 3;
Predicate<Integer> predicate = Predicate.isEqual(num1);
System.out.println(predicate.test(num1));
System.out.println(predicate.test(num2));
}
}
Output -
true
false
The code can also be rewritten as -
System.out.println(Predicate.isEqual(num1).test(num1));
System.out.println(Predicate.isEqual(num1).test(num2));
with same output.
A practical application in Java streams -
Code -
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
public class App {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Elephant");
list.add("Hippo");
list.add("Rhino");
list.add("Deer");
list.add("Hippo");
list.add("Zebra");
Predicate<String> predicate = Predicate.isEqual("Hippo");
list.stream().filter(predicate).forEach(System.out::println);
}
}
Output -
Hippo
Hippo
I would like to avoid the mutation of the input list of iterators tests by others. I only want others to run on a deep copy of tests.
How can this be achieved in Java?
Here is an example showing the effect of the mutation on tests. Both of the two parts are sorting the input. But the second part has nothing to be sorted since the mutation from the first part iterated the iterators to the end.
You can run the following example online here:
https://onlinegdb.com/NC4WzLzmt
import java.util.*;
public class ImmutableExample {
public static void main(String[] args) {
System.out.println("sort on demand");
List<Iterator<Integer>> mutableTests = Arrays.asList(
Arrays.asList(1, 2).iterator(),
Arrays.asList(0).iterator(),
Collections.emptyIterator()
);
List<Iterator<Integer>> tests = Collections.unmodifiableList(mutableTests);
MergingIterator mergingIterator = new MergingIterator(tests);
while (mergingIterator.hasNext()) {
System.out.println(mergingIterator.next());
}
System.out.println("sort all at once");
/* uncomment the following will see the same result:*/
// tests = Arrays.asList(
// Arrays.asList(1, 2).iterator(),
// Arrays.asList(0).iterator(),
// Collections.emptyIterator()
// );
MergeKSortedIterators sol = new MergeKSortedIterators();
Iterable<Integer> result = sol.mergeKSortedIterators(tests);
for (Integer num : result) {
System.out.println(num);
}
}
}
class PeekingIterator implements Iterator<Integer>, Comparable<PeekingIterator> {
Iterator<Integer> iterator;
Integer peekedElement;
boolean hasPeeked;
public PeekingIterator(Iterator<Integer> iterator) {
this.iterator = iterator;
}
public boolean hasNext() {
return hasPeeked || iterator.hasNext();
}
public Integer next() {
int nextElem = hasPeeked ? peekedElement : iterator.next();
hasPeeked = false;
return nextElem;
}
public Integer peek() {
peekedElement = hasPeeked ? peekedElement : iterator.next();
hasPeeked = true;
return peekedElement;
}
#Override
public int compareTo(PeekingIterator that) {
return this.peek() - that.peek();
}
}
class MergingIterator implements Iterator<Integer> {
Queue<PeekingIterator> minHeap;
public MergingIterator(List<Iterator<Integer>> iterators) {
// minHeap = new PriorityQueue<>((x, y) -> x.peek().compareTo(y.peek()));
minHeap = new PriorityQueue<>();
for (Iterator<Integer> iterator : iterators) {
if (iterator.hasNext()) {
minHeap.offer(new PeekingIterator(iterator));
}
}
}
public boolean hasNext() {
return !minHeap.isEmpty();
}
public Integer next() {
PeekingIterator nextIter = minHeap.poll();
Integer next = nextIter.next();
if (nextIter.hasNext()) {
minHeap.offer(nextIter);
}
return next;
}
}
class MergeKSortedIterators {
public Iterable<Integer> mergeKSortedIterators(List<Iterator<Integer>> iteratorList) {
List<Integer> result = new ArrayList<>();
if (iteratorList.isEmpty()) {
return result;
}
PriorityQueue<PeekingIterator> pq = new PriorityQueue<>();
for (Iterator<Integer> iterator : iteratorList) {
if (iterator.hasNext()) {
pq.add(new PeekingIterator(iterator));
}
}
while (!pq.isEmpty()) {
PeekingIterator curr = pq.poll();
// result.add(curr.peek());
// cannot use this one as hasNext() checks on `hasPeeked`
result.add(curr.next());
if (curr.hasNext()) {
pq.add(curr);
}
}
return result;
}
}
This question seems to be based on a misunderstanding ... or two.
How can I prevent mutation of a list of iterators?
You need to distinguish between the mutability of a list, and the mutability of the items in the list. I think you are actually asking about the latter. (And as such, the list is not really relevant to the question. As we shall see.)
I would like to avoid the mutation of the input list of iterators tests by others.
Again, you appear to be asking about the list, but I think you actually mean to ask about the iterators.
I only want others to run on a deep copy of tests.
This implies you want the iterators to be immutable.
Here's the problem:
An Iterator is an inherently stateful / mutable object. Indeed, there is no way to implement next() without mutating the iterator object.
Iterator objects are typically not deep copyable. They typically don't support clone() or public constructors, and they typically do not implement Serializable. (Indeed, if they were serializable, the semantics of serialize / deserialize would be problematic.)
So basically, your idea of a list of immutable iterators or a list that (somehow) produces deep copies of iterators is not practical.
You commented:
So List<Iterator<Integer>> tests = Collections.unmodifiableList(mutableTests); cannot produce an unmodifiable list for List<Iterator<Integer>>?
Well, yes it can. But that doesn't solve the problem. You need a list of unmodifiable iterators rather than an unmodifiable list of iterators.
Possible solutions:
You could just recreate the list of iterators from their base collections for each test run.
Use Iterable instead of Iterator. The collection types you are using all implement Iterable, and the third iterator could be created from an empty list.
List<Iterable<Integer>> tests = Arrays.asList(
Arrays.asList(1, 2),
Arrays.asList(0),
Collections.emptyList()
);
// to use them ...
for (Iterable<Integer> iterable : tests) {
Iterator<Integer> iterator = iterable.iterator();
// etc ...
}
If your iterators could not be recreated (for example, if you were iterating a source that couldn't be created or "rewound"), you could conceivably implement a caching iterator wrapper that remembered all of the elements in the iteration sequence and could either reset to the start of the sequence, or generate a new iterator to replay the sequence. (But that would be overkill here.)
I'm trying to understand how to use a method that uses generic. And I want to create a generic method that can passing data to it. for example I want to create an array and add it with a variable in that Method. Byetheway I'm using Java
this is the code that i was Trying:
public class test {
static int d;
public static <E> void AdditionArray (E[] arr, int var) {
for (E element : arr) {
d = element + var; //this is the big problem, I have no idea whether this is possible or not
System.out.println(d);
}
}
public static void main(String[] args) {
Integer [] arr1 = {1,4,5,7};
AdditionArray(arr1, 2);
}
}
so one line of my codes definitely was wrong, but how can i do that ?
a Method that using Generic and passing data to it ?
If you want use generic to add array element consider extending Number type
for instance:
public class Main {
static int d;
public static <E extends Number> void AdditionArray(E[] arr, int var) {
for (E element : arr) {
d = element.intValue() + var; //this is the big problem, I have no idea whether this is possible or not
System.out.println(d);
}
}
static String z;
public static <E extends CharSequence> void AdditionArray2(E[] arr, int var) {
for (E element : arr) {
z += element.toString() + var; //this is the big problem, I have no idea whether this is possible or not
System.out.println(z);
}
}
public static void main(String[] args) {
Integer[] arr1 = {1, 4, 5, 7};
AdditionArray(arr1, 2);
Double[] arr2 = {1.0, 4.0, 5.0, 7.0};
AdditionArray(arr2, 2);
String[] arr3 = {"a", "b", "c", "d"};
AdditionArray2(arr3, 2);
}
}
If you are familiar with what a Lambda is, you can do this very succinctly in Java 8+ using lambdas.
Here's an example
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
public class GenericAddition {
public static <E> List<E> map(List<E> elements, Function<E, E> mapper) {
List<E> result = new ArrayList<>();
for (E element : elements) {
result.add(mapper.apply(element));
}
return result;
}
public static void main(String...args) {
List<Integer> addedThree = map(Arrays.asList(5, 3, 4), (elem) -> elem + 3);
System.out.println(addedThree);
List<String> concatted = map(Arrays.asList("good", "guten", "baz"), (elem) -> elem + " day");
System.out.println(concatted);
}
}
This will print out:
[8, 6, 7]
[good day, guten day, baz day]
One catch is you have to use a List type because using E[] could be an array of primitives but your mapper function needs to take in objects (since type parameters must be of object types). You could easily code around this restriction by adding a wrapper function that converts an array to a list, Java will be smart and perform auto-boxing for you in that case.
I personally think this is very readable and also very flexible since you can define any kind of logic for performing the mapping i.e. if I wanted to do something like add 5 if its odd, or *2 if its even, I can define my own lambda function for doing this. That way, I can get more complex behavior without having to write separate methods for each different type that I want.
If you are using an older Java version, you could do the same thing with anonymous inner classes that implement a particular interface.
I would like to remove an element from an ArrayList in Java if it meets a certain criteria.
ie:
for (Pulse p : pulseArray) {
if (p.getCurrent() == null) {
pulseArray.remove(p);
}
}
I can understand why this does not work, but what is a good way to do this?
You can use Collection::removeIf(Predicate filter) (available from Java8 onwards), here is a simple example:
final Collection<Integer> list = new ArrayList<>(Arrays.asList(1, 2));
list.removeIf(value -> value < 2);
System.out.println(list); // outputs "[2]"
You must use an Iterator to iterate and the remove function of the iterator (not of the list) :
Iterator<Pulse> iter = pulseArray.iterator();
while (iter.hasNext()) {
Pulse p = iter.next();
if (p.getCurrent()==null) iter.remove();
}
Note that the Iterator#remove function is said to be optionnal but it is implemented by the ArrayList's iterator.
Here's the code of this concrete function from ArrayList.java :
765 public void remove() {
766 if (lastRet < 0)
767 throw new IllegalStateException();
768 checkForComodification();
769
770 try {
771 ArrayList.this.remove(lastRet);
772 cursor = lastRet;
773 lastRet = -1;
774 expectedModCount = modCount;
775 } catch (IndexOutOfBoundsException ex) {
776 throw new ConcurrentModificationException();
777 }
778 }
779
780 final void checkForComodification() {
781 if (modCount != expectedModCount)
782 throw new ConcurrentModificationException();
783 }
784 }
The expectedModCount = modCount; line is why it won't throw an exception when you use it while iterating.
No need to use iterator. With Java 8 (streaming and filtering capability and lambdas) you can accomplish it using one line.
For eg. the required code that does the operation you specified will be :
pulseArray = pulseArray.stream().filter(pulse -> pulse != null).collect(Collectors.toList());
You can implement interface Predicate overriding abstract method boolean test(T);
Use removeIf(Predicate p) method to remove all matching elements from your
list.
For example:
List<Book> bookList = new ArrayList<>();
bookList.add(new Book(101, "bookname1"));
bookList.add(new Book(102, "booknamelong2"));
bookList.removeIf(new LongBookNames())
public class LongBookNames implements Predicate<Book> {
#Override
public boolean test(Book book) {
return book.getBookName.length() >10;
}
}
When you are removing the element from the same list, the index gets disturbed. Try little differently as below:
for (int i=0; i < pulseArray.size(); i++) {
Pulse p = (Pulse)pulseArray.get(i);
if (p.getCurrent() == null) {
pulseArray.remove(p);
i--;//decrease the counter by one
}
}
As an alterative to using an iterator, you can use the Guava collections library. This has the advantage of being more functional (if you are into that sort of thing):
Predicate<Pulse> hasCurrent = new Predicate<Pulse>() {
#Override public boolean apply(Pulse input) {
return (input.getCurrent() != null);
}
};
pulseArray = Lists.newArrayList(Collections2.filter(pulseArray, hasCurrent));
You can't alter a collection that you're iterating through using methods on the collection. However, some iterators (including iterators on ArrayLists) support a remove() method that allows you to remove methods in the order that you're iterating.
Iterator<Pulse> iterator = pulseArray.iterator();
while (iterator.hasNext()) {
Pulse p = iterator.next();
if (p.getCurrent() == null) {
iterator.remove();
}
}
Below one is used when Single ArrayList have multiple types Objects and one object have count == 0 then it removed from pulseArray
Constants.java
public class ViewType {
public static final int PULSE = 101;
public static final int HEARTBEAT = 102;
}
BaseModel.java (This is Base Model)
public interface BaseModel {
int getViewType();
}
PulseModel.java (which implements with BaseModel)
public class PulseModel implements BaseModel {
#Override
public int getViewType() {
return Constants.ViewType.PULSE;
}
#SerializedName("PulseId")
#Expose
private String pulseId;
#SerializedName("Count")
#Expose
private String count;
}
Remove PulseModel object from pulseArray in which Count = 0
pulseArray.removeIf(
(BaseModel model) -> {
boolean remove = false;
if (model instanceof PulseModel) {
remove = (((PulseModel) model).getCount() == 0);
if (remove) {
//Success
}
}
return remove;
});
To remove elements from ArrayList based on a condition or predicate or filter, use removeIf() method. You can call removeIf() method on the ArrayList, with the predicate (filter) passed as argument. All the elements that satisfy the filter (predicate) will be removed from the ArrayList.
arraylist.removeIf(element -> (Objects.equals(element.getId(), id)));
Using an Iterator would give you the power of modifying the list while iterating through the arraylist
Since Java doesn't allow passing methods as parameters, what trick do you use to implement Python like list comprehension in Java ?
I have a list (ArrayList) of Strings. I need to transform each element by using a function so that I get another list. I have several functions which take a String as input and return another String as output. How do I make a generic method which can be given the list and the function as parameters so that I can get a list back with each element processed. It is not possible in the literal sense, but what trick should I use ?
The other option is to write a new function for each smaller String-processing function which simply loops over the entire list, which is kinda not so cool.
In Java 8 you can use method references:
List<String> list = ...;
list.replaceAll(String::toUpperCase);
Or, if you want to create a new list instance:
List<String> upper = list.stream().map(String::toUpperCase).collect(Collectors.toList());
Basically, you create a Function interface:
public interface Func<In, Out> {
public Out apply(In in);
}
and then pass in an anonymous subclass to your method.
Your method could either apply the function to each element in-place:
public static <T> void applyToListInPlace(List<T> list, Func<T, T> f) {
ListIterator<T> itr = list.listIterator();
while (itr.hasNext()) {
T output = f.apply(itr.next());
itr.set(output);
}
}
// ...
List<String> myList = ...;
applyToListInPlace(myList, new Func<String, String>() {
public String apply(String in) {
return in.toLowerCase();
}
});
or create a new List (basically creating a mapping from the input list to the output list):
public static <In, Out> List<Out> map(List<In> in, Func<In, Out> f) {
List<Out> out = new ArrayList<Out>(in.size());
for (In inObj : in) {
out.add(f.apply(inObj));
}
return out;
}
// ...
List<String> myList = ...;
List<String> lowerCased = map(myList, new Func<String, String>() {
public String apply(String in) {
return in.toLowerCase();
}
});
Which one is preferable depends on your use case. If your list is extremely large, the in-place solution may be the only viable one; if you wish to apply many different functions to the same original list to make many derivative lists, you will want the map version.
The Google Collections library has lots of classes for working with collections and iterators at a much higher level than plain Java supports, and in a functional manner (filter, map, fold, etc.). It defines Function and Predicate interfaces and methods that use them to process collections so that you don't have to. It also has convenience functions that make dealing with Java generics less arduous.
I also use Hamcrest** for filtering collections.
The two libraries are easy to combine with adapter classes.
** Declaration of interest: I co-wrote Hamcrest
Apache Commons CollectionsUtil.transform(Collection, Transformer) is another option.
I'm building this project to write list comprehension in Java, now is a proof of concept in https://github.com/farolfo/list-comprehension-in-java
Examples
// { x | x E {1,2,3,4} ^ x is even }
// gives {2,4}
Predicate<Integer> even = x -> x % 2 == 0;
List<Integer> evens = new ListComprehension<Integer>()
.suchThat(x -> {
x.belongsTo(Arrays.asList(1, 2, 3, 4));
x.is(even);
});
// evens = {2,4};
And if we want to transform the output expression in some way like
// { x * 2 | x E {1,2,3,4} ^ x is even }
// gives {4,8}
List<Integer> duplicated = new ListComprehension<Integer>()
.giveMeAll((Integer x) -> x * 2)
.suchThat(x -> {
x.belongsTo(Arrays.asList(1, 2, 3, 4));
x.is(even);
});
// duplicated = {4,8}
You can use lambdas for the function, like so:
class Comprehension<T> {
/**
*in: List int
*func: Function to do to each entry
*/
public List<T> comp(List<T> in, Function<T, T> func) {
List<T> out = new ArrayList<T>();
for(T o: in) {
out.add(func.apply(o));
}
return out;
}
}
the usage:
List<String> stuff = new ArrayList<String>();
stuff.add("a");
stuff.add("b");
stuff.add("c");
stuff.add("d");
stuff.add("cheese");
List<String> newStuff = new Comprehension<String>().comp(stuff, (a) -> { //The <String> tells the comprehension to return an ArrayList<String>
a.equals("a")? "1":
(a.equals("b")? "2":
(a.equals("c")? "3":
(a.equals("d")? "4": a
)))
});
will return:
["1", "2", "3", "4", "cheese"]
import java.util.Arrays;
class Soft{
public static void main(String[] args){
int[] nums=range(9, 12);
System.out.println(Arrays.toString(nums));
}
static int[] range(int low, int high){
int[] a=new int[high-low];
for(int i=0,j=low;i<high-low;i++,j++){
a[i]=j;
}
return a;
}
}
Hope, that I help you :)