Varargs in a group? - java

About Varargs, can i repeat the arguments in a group?
For instance, i want to allow users pass in:
myFunc(1, "one");
myFunc(1, "one", 2, "two");
myFunc(1, "one", 2, "two", 3, "three");
It seems impossible. But as mentioned in the docs, the varargs is in fact an array, in old implementation. i would like to know how was people do before varargs is invented. That might inspire us how to achieve the above scenario. We can regard my scenario as {int, String}... repeating afterall.
Thanks for any input :-)
Edit:
Thanks for all your inputs!
So, is it calling by myFunc(new wrap(1, "one"), new wrap(2, "two"), new wrap(3, "three")); is the old method?
Edit 2:
Well, nope. Thats my fault of confusion.
For
myFunc(1);
myFunc(1, 2);
myFunc(1, 2, 3);
the old way should be
myFunc(new int[]{1});
myFunc(new int[]{1, 2});
myFunc(new int[]{1, 2, 3});
As far as i can see, as the repeating arguments form an array. All its arguments has to be of the same type. It should be impossible to achieve the above calls in a simple way. For curiosity, i start thinking of the possibility of operator overloading ... (?)

In this case, it seems to me that it's suitable to create a datastructure for your "pair", and then use that type as vararg argument to your method.
public void myFunc(Pair... pairs) {}
You could also use Object..., but I don't see any advantages in this case, since the arguments always come in pairs.

There are good reasons to use the other solutions, but they all introduce a bit of clutter (to create all those objects) you might not want to subject the users of your library to.
You can shift the clutter to the inside of your method like so:
public void example(final Object... args) {
if (args.length % 2 != 0)
throw new IllegalArgumentException("int, String pairs are required, but there seems to be an odd one out");
for (int i = 0; i < args.length; i += 2) {
int a = (Integer) args[i];
String b = (String) args[i + 1];
System.out.printf("%d: %s\n", a, b);
}
}
example(1, "Hello", 2, "Goodbye", 25, "Raptors will eat you!"); will then produce the following output:
1: Hello
2: Goodbye
25: Raptors will eat you!

Var args were introduced to allow you to send an arbitrary number of arguments to a function. Folks hacked around with other Collections / arrays before they came about.
You can achieve what you want with a custom structure. The particulars of the structure will depend on what the name value pair should achieve. Here is a generic solution for any NameValue pair.
NameValuePair
class NameValuePair<K,V>
{
private K key;
private V value;
public K getKey()
{
return key;
}
public void setKey(K key)
{
this.key = key;
}
public V getValue()
{
return value;
}
public void setValue(V value)
{
this.value = value;
}
}
Usage
private <K,V> void method(NameValuePair<K, V>... pairs )
{
for (NameValuePair<K, V> nameValuePair : pairs)
{
K key = nameValuePair.getKey();
V value = nameValuePair.getValue();
// logic goes here
}
}

What about creating a wrapper class that wraps the two parameters together?
public class TwoParameter
{
private int intValue;
private String stringValue;
public TwoParameter(int intValue, String stringValue)
{
this.intValue = intValue;
this.stringValue = stringValue;
}
// getters and setters
}
and then use it like:
myFunc(new TwoParameter(1, "one"), new TwoParameter(2, "two"));
The signature of the method would be something like this:
public void myFunc(TwoParameter... params){...}

Related

An easy way to manage multidimensional array with string and integer keys

I am fairly new in Java, so I have to rely on this community for this one.
I need to store an object in some sort of array/list where I can quickly access the object using a string and two interger keys. Something like a["string"][1][1] - I have looked over some different guides and tutorials, but not been able to come up with a good solution that's easy to manage.
I am creating a Minecraft plugin where I need to keep track of where specific Blocks are with world, chunk_x, and chunk_z- I am trying to create a method where I can provide a location, which has the three beforementioned values, and do a quick look up based on the world and chunk, so I do not have to iterate all stored blocks in the world, but can limit it to 9 chunks of the world. (Current chunk i am in and all surrounding neighbours)
How about this:
Map<String, Object[][]> store;
Does it have to be a multidimensional array? You could use just a hash map with a custom key that holds your string key and the two integer keys. Here is a complete example of what I mean:
import java.util.HashMap;
import java.util.Objects;
public class multidim {
static class Key {
int index0, index1;
String str;
int _hash_code;
public Key(String s, int i0, int i1) {
_hash_code = Objects.hash(s, i0, i1);
str = s;
index0 = i0;
index1 = i1;
}
public int hashCode() {
return _hash_code;
}
public boolean equals(Object x) {
if (this == x) {
return true;
} else if (x == null) {
return false;
} else if (!(x instanceof Key)) {
return false;
}
Key k = (Key)x;
return (index0 == k.index0)
&& (index1 == k.index1)
&& Objects.equals(str, k.str);
}
}
public static void main(String[] args) {
HashMap<Key, Double> m = new HashMap<Key, Double>();
m.put(new Key("mjao", 3, 4), 119.0);
m.put(new Key("katt$k1t", 4, 6), 120.0);
System.out.println("Value that we put before: "
+ m.get(new Key("mjao", 3, 4)));
}
}
We define a class Key that represents the values you use to access elements and we override its equals and hashCode methods so that it can be used in a hash map. Then we just use it with the java.util.HashMap class. Running the above program will output Value that we put before: 119.0.
Edit: Add this == x comparison in equals (a small optimization).
What about combination of Map and Pair?
Map<String, Pair<Integer, Integer>> tripletMap = new HashMap<>;
tripletMap.put(Pair.with(23, 1););
You can access values from your triplet as any map and then retrieved Pair as:
Pair<Integer, Integer> myPair = tripletMap.get("key")
myPair.getValue0()
myPair.getValue1()

Is there a way to check if an object contains certain data? [duplicate]

I want to filter a java.util.Collection based on a predicate.
Java 8 (2014) solves this problem using streams and lambdas in one line of code:
List<Person> beerDrinkers = persons.stream()
.filter(p -> p.getAge() > 16).collect(Collectors.toList());
Here's a tutorial.
Use Collection#removeIf to modify the collection in place. (Notice: In this case, the predicate will remove objects who satisfy the predicate):
persons.removeIf(p -> p.getAge() <= 16);
lambdaj allows filtering collections without writing loops or inner classes:
List<Person> beerDrinkers = select(persons, having(on(Person.class).getAge(),
greaterThan(16)));
Can you imagine something more readable?
Disclaimer: I am a contributor on lambdaj
Assuming that you are using Java 1.5, and that you cannot add Google Collections, I would do something very similar to what the Google guys did. This is a slight variation on Jon's comments.
First add this interface to your codebase.
public interface IPredicate<T> { boolean apply(T type); }
Its implementers can answer when a certain predicate is true of a certain type. E.g. If T were User and AuthorizedUserPredicate<User> implements IPredicate<T>, then AuthorizedUserPredicate#apply returns whether the passed in User is authorized.
Then in some utility class, you could say
public static <T> Collection<T> filter(Collection<T> target, IPredicate<T> predicate) {
Collection<T> result = new ArrayList<T>();
for (T element: target) {
if (predicate.apply(element)) {
result.add(element);
}
}
return result;
}
So, assuming that you have the use of the above might be
Predicate<User> isAuthorized = new Predicate<User>() {
public boolean apply(User user) {
// binds a boolean method in User to a reference
return user.isAuthorized();
}
};
// allUsers is a Collection<User>
Collection<User> authorizedUsers = filter(allUsers, isAuthorized);
If performance on the linear check is of concern, then I might want to have a domain object that has the target collection. The domain object that has the target collection would have filtering logic for the methods that initialize, add and set the target collection.
UPDATE:
In the utility class (let's say Predicate), I have added a select method with an option for default value when the predicate doesn't return the expected value, and also a static property for params to be used inside the new IPredicate.
public class Predicate {
public static Object predicateParams;
public static <T> Collection<T> filter(Collection<T> target, IPredicate<T> predicate) {
Collection<T> result = new ArrayList<T>();
for (T element : target) {
if (predicate.apply(element)) {
result.add(element);
}
}
return result;
}
public static <T> T select(Collection<T> target, IPredicate<T> predicate) {
T result = null;
for (T element : target) {
if (!predicate.apply(element))
continue;
result = element;
break;
}
return result;
}
public static <T> T select(Collection<T> target, IPredicate<T> predicate, T defaultValue) {
T result = defaultValue;
for (T element : target) {
if (!predicate.apply(element))
continue;
result = element;
break;
}
return result;
}
}
The following example looks for missing objects between collections:
List<MyTypeA> missingObjects = (List<MyTypeA>) Predicate.filter(myCollectionOfA,
new IPredicate<MyTypeA>() {
public boolean apply(MyTypeA objectOfA) {
Predicate.predicateParams = objectOfA.getName();
return Predicate.select(myCollectionB, new IPredicate<MyTypeB>() {
public boolean apply(MyTypeB objectOfB) {
return objectOfB.getName().equals(Predicate.predicateParams.toString());
}
}) == null;
}
});
The following example, looks for an instance in a collection, and returns the first element of the collection as default value when the instance is not found:
MyType myObject = Predicate.select(collectionOfMyType, new IPredicate<MyType>() {
public boolean apply(MyType objectOfMyType) {
return objectOfMyType.isDefault();
}}, collectionOfMyType.get(0));
UPDATE (after Java 8 release):
It's been several years since I (Alan) first posted this answer, and I still cannot believe I am collecting SO points for this answer. At any rate, now that Java 8 has introduced closures to the language, my answer would now be considerably different, and simpler. With Java 8, there is no need for a distinct static utility class. So if you want to find the 1st element that matches your predicate.
final UserService userService = ... // perhaps injected IoC
final Optional<UserModel> userOption = userCollection.stream().filter(u -> {
boolean isAuthorized = userService.isAuthorized(u);
return isAuthorized;
}).findFirst();
The JDK 8 API for optionals has the ability to get(), isPresent(), orElse(defaultUser), orElseGet(userSupplier) and orElseThrow(exceptionSupplier), as well as other 'monadic' functions such as map, flatMap and filter.
If you want to simply collect all the users which match the predicate, then use the Collectors to terminate the stream in the desired collection.
final UserService userService = ... // perhaps injected IoC
final List<UserModel> userOption = userCollection.stream().filter(u -> {
boolean isAuthorized = userService.isAuthorized(u);
return isAuthorized;
}).collect(Collectors.toList());
See here for more examples on how Java 8 streams work.
Use CollectionUtils.filter(Collection,Predicate), from Apache Commons.
"Best" way is too wide a request. Is it "shortest"? "Fastest"? "Readable"?
Filter in place or into another collection?
Simplest (but not most readable) way is to iterate it and use Iterator.remove() method:
Iterator<Foo> it = col.iterator();
while( it.hasNext() ) {
Foo foo = it.next();
if( !condition(foo) ) it.remove();
}
Now, to make it more readable, you can wrap it into a utility method. Then invent a IPredicate interface, create an anonymous implementation of that interface and do something like:
CollectionUtils.filterInPlace(col,
new IPredicate<Foo>(){
public boolean keepIt(Foo foo) {
return foo.isBar();
}
});
where filterInPlace() iterate the collection and calls Predicate.keepIt() to learn if the instance to be kept in the collection.
I don't really see a justification for bringing in a third-party library just for this task.
Consider Google Collections for an updated Collections framework that supports generics.
UPDATE: The google collections library is now deprecated. You should use the latest release of Guava instead. It still has all the same extensions to the collections framework including a mechanism for filtering based on a predicate.
Wait for Java 8:
List<Person> olderThan30 =
//Create a Stream from the personList
personList.stream().
//filter the element to select only those with age >= 30
filter(p -> p.age >= 30).
//put those filtered elements into a new List.
collect(Collectors.toList());
Since the early release of Java 8, you could try something like:
Collection<T> collection = ...;
Stream<T> stream = collection.stream().filter(...);
For example, if you had a list of integers and you wanted to filter the numbers that are > 10 and then print out those numbers to the console, you could do something like:
List<Integer> numbers = Arrays.asList(12, 74, 5, 8, 16);
numbers.stream().filter(n -> n > 10).forEach(System.out::println);
I'll throw RxJava in the ring, which is also available on Android. RxJava might not always be the best option, but it will give you more flexibility if you wish add more transformations on your collection or handle errors while filtering.
Observable.from(Arrays.asList(1, 2, 3, 4, 5))
.filter(new Func1<Integer, Boolean>() {
public Boolean call(Integer i) {
return i % 2 != 0;
}
})
.subscribe(new Action1<Integer>() {
public void call(Integer i) {
System.out.println(i);
}
});
Output:
1
3
5
More details on RxJava's filter can be found here.
The setup:
public interface Predicate<T> {
public boolean filter(T t);
}
void filterCollection(Collection<T> col, Predicate<T> predicate) {
for (Iterator i = col.iterator(); i.hasNext();) {
T obj = i.next();
if (predicate.filter(obj)) {
i.remove();
}
}
}
The usage:
List<MyObject> myList = ...;
filterCollection(myList, new Predicate<MyObject>() {
public boolean filter(MyObject obj) {
return obj.shouldFilter();
}
});
How about some plain and straighforward Java
List<Customer> list ...;
List<Customer> newList = new ArrayList<>();
for (Customer c : list){
if (c.getName().equals("dd")) newList.add(c);
}
Simple, readable and easy (and works in Android!)
But if you're using Java 8 you can do it in a sweet one line:
List<Customer> newList = list.stream().filter(c -> c.getName().equals("dd")).collect(toList());
Note that toList() is statically imported
Are you sure you want to filter the Collection itself, rather than an iterator?
see org.apache.commons.collections.iterators.FilterIterator
or using version 4 of apache commons org.apache.commons.collections4.iterators.FilterIterator
Since java 9 Collectors.filtering is enabled:
public static <T, A, R>
Collector<T, ?, R> filtering(Predicate<? super T> predicate,
Collector<? super T, A, R> downstream)
Thus filtering should be:
collection.stream().collect(Collectors.filtering(predicate, collector))
Example:
List<Integer> oddNumbers = List.of(1, 19, 15, 10, -10).stream()
.collect(Collectors.filtering(i -> i % 2 == 1, Collectors.toList()));
Let’s look at how to filter a built-in JDK List and a MutableList using Eclipse Collections.
List<Integer> jdkList = Arrays.asList(1, 2, 3, 4, 5);
MutableList<Integer> ecList = Lists.mutable.with(1, 2, 3, 4, 5);
If you wanted to filter the numbers less than 3, you would expect the following outputs.
List<Integer> selected = Lists.mutable.with(1, 2);
List<Integer> rejected = Lists.mutable.with(3, 4, 5);
Here’s how you can filter using a Java 8 lambda as the Predicate.
Assert.assertEquals(selected, Iterate.select(jdkList, each -> each < 3));
Assert.assertEquals(rejected, Iterate.reject(jdkList, each -> each < 3));
Assert.assertEquals(selected, ecList.select(each -> each < 3));
Assert.assertEquals(rejected, ecList.reject(each -> each < 3));
Here’s how you can filter using an anonymous inner class as the Predicate.
Predicate<Integer> lessThan3 = new Predicate<Integer>()
{
public boolean accept(Integer each)
{
return each < 3;
}
};
Assert.assertEquals(selected, Iterate.select(jdkList, lessThan3));
Assert.assertEquals(selected, ecList.select(lessThan3));
Here are some alternatives to filtering JDK lists and Eclipse Collections MutableLists using the Predicates factory.
Assert.assertEquals(selected, Iterate.select(jdkList, Predicates.lessThan(3)));
Assert.assertEquals(selected, ecList.select(Predicates.lessThan(3)));
Here is a version that doesn't allocate an object for the predicate, by using the Predicates2 factory instead with the selectWith method that takes a Predicate2.
Assert.assertEquals(
selected, ecList.selectWith(Predicates2.<Integer>lessThan(), 3));
Sometimes you want to filter on a negative condition. There is a special method in Eclipse Collections for that called reject.
Assert.assertEquals(rejected, Iterate.reject(jdkList, lessThan3));
Assert.assertEquals(rejected, ecList.reject(lessThan3));
The method partition will return two collections, containing the elements selected by and rejected by the Predicate.
PartitionIterable<Integer> jdkPartitioned = Iterate.partition(jdkList, lessThan3);
Assert.assertEquals(selected, jdkPartitioned.getSelected());
Assert.assertEquals(rejected, jdkPartitioned.getRejected());
PartitionList<Integer> ecPartitioned = gscList.partition(lessThan3);
Assert.assertEquals(selected, ecPartitioned.getSelected());
Assert.assertEquals(rejected, ecPartitioned.getRejected());
Note: I am a committer for Eclipse Collections.
With the ForEach DSL you may write
import static ch.akuhn.util.query.Query.select;
import static ch.akuhn.util.query.Query.$result;
import ch.akuhn.util.query.Select;
Collection<String> collection = ...
for (Select<String> each : select(collection)) {
each.yield = each.value.length() > 3;
}
Collection<String> result = $result();
Given a collection of [The, quick, brown, fox, jumps, over, the, lazy, dog] this results in [quick, brown, jumps, over, lazy], ie all strings longer than three characters.
All iteration styles supported by the ForEach DSL are
AllSatisfy
AnySatisfy
Collect
Counnt
CutPieces
Detect
GroupedBy
IndexOf
InjectInto
Reject
Select
For more details, please refer to https://www.iam.unibe.ch/scg/svn_repos/Sources/ForEach
The Collections2.filter(Collection,Predicate) method in Google's Guava library does just what you're looking for.
This, combined with the lack of real closures, is my biggest gripe for Java.
Honestly, most of the methods mentioned above are pretty easy to read and REALLY efficient; however, after spending time with .Net, Erlang, etc... list comprehension integrated at the language level makes everything so much cleaner. Without additions at the language level, Java just cant be as clean as many other languages in this area.
If performance is a huge concern, Google collections is the way to go (or write your own simple predicate utility). Lambdaj syntax is more readable for some people, but it is not quite as efficient.
And then there is a library I wrote. I will ignore any questions in regard to its efficiency (yea, its that bad)...... Yes, i know its clearly reflection based, and no I don't actually use it, but it does work:
LinkedList<Person> list = ......
LinkedList<Person> filtered =
Query.from(list).where(Condition.ensure("age", Op.GTE, 21));
OR
LinkedList<Person> list = ....
LinkedList<Person> filtered = Query.from(list).where("x => x.age >= 21");
In Java 8, You can directly use this filter method and then do that.
List<String> lines = Arrays.asList("java", "pramod", "example");
List<String> result = lines.stream()
.filter(line -> !"pramod".equals(line))
.collect(Collectors.toList());
result.forEach(System.out::println);
JFilter http://code.google.com/p/jfilter/ is best suited for your requirement.
JFilter is a simple and high performance open source library to query collection of Java beans.
Key features
Support of collection (java.util.Collection, java.util.Map and Array) properties.
Support of collection inside collection of any depth.
Support of inner queries.
Support of parameterized queries.
Can filter 1 million records in few 100 ms.
Filter ( query) is given in simple json format, it is like Mangodb queries. Following are some examples.
{ "id":{"$le":"10"}
where object id property is less than equals to 10.
{ "id": {"$in":["0", "100"]}}
where object id property is 0 or 100.
{"lineItems":{"lineAmount":"1"}}
where lineItems collection property of parameterized type has lineAmount equals to 1.
{ "$and":[{"id": "0"}, {"billingAddress":{"city":"DEL"}}]}
where id property is 0 and billingAddress.city property is DEL.
{"lineItems":{"taxes":{ "key":{"code":"GST"}, "value":{"$gt": "1.01"}}}}
where lineItems collection property of parameterized type which has taxes map type property of parameteriszed type has code equals to GST value greater than 1.01.
{'$or':[{'code':'10'},{'skus': {'$and':[{'price':{'$in':['20', '40']}}, {'code':'RedApple'}]}}]}
Select all products where product code is 10 or sku price in 20 and 40 and sku code is "RedApple".
I wrote an extended Iterable class that support applying functional algorithms without copying the collection content.
Usage:
List<Integer> myList = new ArrayList<Integer>(){ 1, 2, 3, 4, 5 }
Iterable<Integer> filtered = Iterable.wrap(myList).select(new Predicate1<Integer>()
{
public Boolean call(Integer n) throws FunctionalException
{
return n % 2 == 0;
}
})
for( int n : filtered )
{
System.out.println(n);
}
The code above will actually execute
for( int n : myList )
{
if( n % 2 == 0 )
{
System.out.println(n);
}
}
Use Collection Query Engine (CQEngine). It is by far the fastest way to do this.
See also: How do you query object collections in Java (Criteria/SQL-like)?
Using java 8, specifically lambda expression, you can do it simply like the below example:
myProducts.stream().filter(prod -> prod.price>10).collect(Collectors.toList())
where for each product inside myProducts collection, if prod.price>10, then add this product to the new filtered list.
Some really great great answers here. Me, I'd like to keep thins as simple and readable as possible:
public abstract class AbstractFilter<T> {
/**
* Method that returns whether an item is to be included or not.
* #param item an item from the given collection.
* #return true if this item is to be included in the collection, false in case it has to be removed.
*/
protected abstract boolean excludeItem(T item);
public void filter(Collection<T> collection) {
if (CollectionUtils.isNotEmpty(collection)) {
Iterator<T> iterator = collection.iterator();
while (iterator.hasNext()) {
if (excludeItem(iterator.next())) {
iterator.remove();
}
}
}
}
}
The simple pre-Java8 solution:
ArrayList<Item> filtered = new ArrayList<Item>();
for (Item item : items) if (condition(item)) filtered.add(item);
Unfortunately this solution isn't fully generic, outputting a list rather than the type of the given collection. Also, bringing in libraries or writing functions that wrap this code seems like overkill to me unless the condition is complex, but then you can write a function for the condition.
https://code.google.com/p/joquery/
Supports different possibilities,
Given collection,
Collection<Dto> testList = new ArrayList<>();
of type,
class Dto
{
private int id;
private String text;
public int getId()
{
return id;
}
public int getText()
{
return text;
}
}
Filter
Java 7
Filter<Dto> query = CQ.<Dto>filter(testList)
.where()
.property("id").eq().value(1);
Collection<Dto> filtered = query.list();
Java 8
Filter<Dto> query = CQ.<Dto>filter(testList)
.where()
.property(Dto::getId)
.eq().value(1);
Collection<Dto> filtered = query.list();
Also,
Filter<Dto> query = CQ.<Dto>filter()
.from(testList)
.where()
.property(Dto::getId).between().value(1).value(2)
.and()
.property(Dto::grtText).in().value(new string[]{"a","b"});
Sorting (also available for the Java 7)
Filter<Dto> query = CQ.<Dto>filter(testList)
.orderBy()
.property(Dto::getId)
.property(Dto::getName)
Collection<Dto> sorted = query.list();
Grouping (also available for the Java 7)
GroupQuery<Integer,Dto> query = CQ.<Dto,Dto>query(testList)
.group()
.groupBy(Dto::getId)
Collection<Grouping<Integer,Dto>> grouped = query.list();
Joins (also available for the Java 7)
Given,
class LeftDto
{
private int id;
private String text;
public int getId()
{
return id;
}
public int getText()
{
return text;
}
}
class RightDto
{
private int id;
private int leftId;
private String text;
public int getId()
{
return id;
}
public int getLeftId()
{
return leftId;
}
public int getText()
{
return text;
}
}
class JoinedDto
{
private int leftId;
private int rightId;
private String text;
public JoinedDto(int leftId,int rightId,String text)
{
this.leftId = leftId;
this.rightId = rightId;
this.text = text;
}
public int getLeftId()
{
return leftId;
}
public int getRightId()
{
return rightId;
}
public int getText()
{
return text;
}
}
Collection<LeftDto> leftList = new ArrayList<>();
Collection<RightDto> rightList = new ArrayList<>();
Can be Joined like,
Collection<JoinedDto> results = CQ.<LeftDto, LeftDto>query().from(leftList)
.<RightDto, JoinedDto>innerJoin(CQ.<RightDto, RightDto>query().from(rightList))
.on(LeftFyo::getId, RightDto::getLeftId)
.transformDirect(selection -> new JoinedDto(selection.getLeft().getText()
, selection.getLeft().getId()
, selection.getRight().getId())
)
.list();
Expressions
Filter<Dto> query = CQ.<Dto>filter()
.from(testList)
.where()
.exec(s -> s.getId() + 1).eq().value(2);
My answer builds on that from Kevin Wong, here as a one-liner using CollectionUtils from spring and a Java 8 lambda expression.
CollectionUtils.filter(list, p -> ((Person) p).getAge() > 16);
This is as concise and readable as any alternative I have seen (without using aspect-based libraries)
Spring CollectionUtils is available from spring version 4.0.2.RELEASE, and remember you need JDK 1.8 and language level 8+.
I needed to filter a list depending on the values already present in the list. For example, remove all values following that is less than the current value. {2 5 3 4 7 5} -> {2 5 7}. Or for example to remove all duplicates {3 5 4 2 3 5 6} -> {3 5 4 2 6}.
public class Filter {
public static <T> void List(List<T> list, Chooser<T> chooser) {
List<Integer> toBeRemoved = new ArrayList<>();
leftloop:
for (int right = 1; right < list.size(); ++right) {
for (int left = 0; left < right; ++left) {
if (toBeRemoved.contains(left)) {
continue;
}
Keep keep = chooser.choose(list.get(left), list.get(right));
switch (keep) {
case LEFT:
toBeRemoved.add(right);
continue leftloop;
case RIGHT:
toBeRemoved.add(left);
break;
case NONE:
toBeRemoved.add(left);
toBeRemoved.add(right);
continue leftloop;
}
}
}
Collections.sort(toBeRemoved, new Comparator<Integer>() {
#Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
for (int i : toBeRemoved) {
if (i >= 0 && i < list.size()) {
list.remove(i);
}
}
}
public static <T> void List(List<T> list, Keeper<T> keeper) {
Iterator<T> iterator = list.iterator();
while (iterator.hasNext()) {
if (!keeper.keep(iterator.next())) {
iterator.remove();
}
}
}
public interface Keeper<E> {
boolean keep(E obj);
}
public interface Chooser<E> {
Keep choose(E left, E right);
}
public enum Keep {
LEFT, RIGHT, BOTH, NONE;
}
}
This will bee used like this.
List<String> names = new ArrayList<>();
names.add("Anders");
names.add("Stefan");
names.add("Anders");
Filter.List(names, new Filter.Chooser<String>() {
#Override
public Filter.Keep choose(String left, String right) {
return left.equals(right) ? Filter.Keep.LEFT : Filter.Keep.BOTH;
}
});
In my case, I was looking for list with specific field null excluded.
This could be done with for loop and fill the temporary list of objects who have no null addresses.
but Thanks to Java 8 Streams
List<Person> personsList = persons.stream()
.filter(p -> p.getAdrress() != null).collect(Collectors.toList());
#java #collection #collections #java8 #streams
With Guava:
Collection<Integer> collection = Lists.newArrayList(1, 2, 3, 4, 5);
Iterators.removeIf(collection.iterator(), new Predicate<Integer>() {
#Override
public boolean apply(Integer i) {
return i % 2 == 0;
}
});
System.out.println(collection); // Prints 1, 3, 5
An alternative (more lightweight) alternative to Java collection streams is the Ocl.java library, which uses vanilla collections and lambdas: https://github.com/eclipse/agileuml/blob/master/Ocl.java
For example, a simple filter and sum on an ArrayList words
could be:
ArrayList<Word> sel = Ocl.selectSequence(words,
w -> w.pos.equals("NN"));
int total = Ocl.sumint(Ocl.collectSequence(sel,
w -> w.text.length()));
Where Word has String pos; String text; attributes. Efficiency seems similar to the streams option, eg, 10000 words are processed in about 50ms in both versions.
There are equivalent OCL libraries for Python, Swift, etc. Basically Java collection streams has re-invented the OCL operations ->select, ->collect, etc, which existed in OCL since 1998.

Re-order two values from an alphabetically ordered list. Enum/Comparataor

coded list of values A,B,C,D,E,F,G....
I want D to be placed before C while iterating through the list in the JSP.
I'm open for enum or to use comparators.
Currently the enum SortOrder is different object from the Comparable which i currently have.
So how can i deal with this below code.
//override
public int compareTo(Alphabets) {
return name.toLowerCase().compareTo(o.getName().toLowerCase());
}
I've tried
private SortOrder so
public void setName(String name) {
this.name = so.values().toString();
}
But it throws "The static method values() from the type SortOrder should be accessed in a static way"
Please help me.
I've tried stackoverflow and found this, which is close, but not enough:
Java Sorting based on Enum constants
Edit: sorry to confuse everyone, the above question is just a representation of what my issue is. The words which i have for A,B,C,.. have a different presentation in my code.
I have a list of brand names for a product, where i want to re-order the list.
Basically, you're happy with the default compareTo, but you want just a little bit of difference, right?
if (this.name.equals("D2") && that.name.equals("D1")) return -1;
if (this.name.equals("D1") && that.name.equals("D2")) return 1;
return super.compareTo(that);
I'm still not quite sure I understand your question, but if I do, here are two solutions:
With enum
Smallest solution, limited to possible names for enum values. demo
enum SortOrderEnum {
A, B, D, C, E, F;
}
Sort with
Collections.sort(testData, new Comparator<String>() {
#Override
public int compare(String s1, String s2) {
return SortOrderEnum.valueOf(s1).compareTo(SortOrderEnum.valueOf(s2));
}
});
Without enum
You can put any string you want, I didn't see the point of using an enum in this solution. We put the expected index for each string in a static map. demo
public class SortOrder {
public static final Map<String, Integer> SORT_ORDER = initializeSortOrder();
private static Map<String, Integer> initializeSortOrder() {
List<String> orderedStrings = Arrays.asList(
"A",
"B",
"D",
"C",
"E",
"F"
);
Map<String, Integer> indexByString = new HashMap<>();
for (int index = 0; index < orderedStrings.size(); ++index) {
indexByString.put(orderedStrings.get(index), index);
}
return Collections.unmodifiableMap(indexByString);
}
}
Sort with
Collections.sort(testData, new Comparator<String>() {
#Override
public int compare(String s1, String s2) {
return SORT_ORDER.get(s1).compareTo(SORT_ORDER.get(s2));
}
});
Note that this is an example of how to fill the map. You can (better) fill the string->index map from a configuration file.
You can also not put the map in a static variable if that causes problems for you.

Sequential Searching

Ok I am relatively new to Java Programming, but have previous experience in C++. I want to search an array for a specific item, but what if there are more than one of the same specific item? Would it be best to use a temporary array to store all found items in the array and return the temporary array?
Note: I'm trying to find the best way of doing this with memory management and speed. And it's not for Home work:)
Use apache commons lib, which solve a lot of issues. Use this if you want to filter by predicate and select sub array
CollectionUtils.filter(
Arrays.asList(new Integer[] {1,2,3,4,5}),
new Predicate() {
public boolean evaluate(final Object object) {
return ((Integer) object) > 2;
}
}
);
In case if you would like to select item(s) use
CollectionUtils.select(Collection inputCollection, Predicate predicate)
Use true java way - Navigable set and maps
NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
E toElement, boolean toInclusive);
If you able to skip Java, then in Scala it will be much easier:
scala> val a = Array(4, 6, 8, 9, 4, 2, 4, 2)
a: Array[Int] = Array(4, 6, 8, 9, 4, 2, 4, 2)
scala> a.filter(_ == 4)
res0: Array[Int] = Array(4, 4, 4)
just use guava library as the simplest solution:
http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Iterables.html
or
http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Collections2.html
Just use an ArrayList. Example:
/** Returns all strings starting with the letter a.*/
public static List<String> getStartsWithA(String[] strs) {
List<String> ret = new ArrayList<String>();
for (String s: strs) {
if (s.startsWith("a") || s.startsWith("A")) {
ret.add(s);
}
}
return ret;
}
ArrayList's internal array will dynamically grow as more space is needed.
I would use a "ready to use" implementation like a HashMap. You say "search", so I believe that you have a searchkey (in my proposal the String) under wich you can store your data (for example an Integer).
Map<String, List<Integer>> map = new HashMap<String, List<Integer>>();
void storeValue(final String key, final Integer value) {
List<Integer> l = this.map.get(key);
if (l == null) {
synchronized (this.map) {
if (l == null) {
l = new Vector<Integer>();
this.map.put(key, l);
}
}
}
l.add(value);
}
List<Integer> searchByKey(final String key) {
return this.map.get(key);
}
With this, you can store multiple Integers # one key. Of course you can store other Object than the Integers.

List Sorting puzzle

Assuming I have
final Iterable<String> unsorted = asList("FOO", "BAR", "PREFA", "ZOO", "PREFZ", "PREFOO");
What can I do to transform this unsorted list into this:
[PREFZ, PREFA, BAR, FOO, PREFOO, ZOO]
(a list which begin with known values that must appears first (here "PREFA" and "PREFZ") and the rest is alphabetically sorted)
I think there are some usefull classes in guava that can make the job (Ordering, Predicates...), but I have not yet found a solution...
I would keep separate lists.
One for known values and unknown values. And sort them separately, when you need them in a one list you can just concatenate them.
knownUnsorted.addAll(unsorted.size - 1, unknonwUnsorted);
I suggest filling List with your values and using Collections.sort(...).
Something like
Collections.sort(myList, new FunkyComparator());
using this:
class FunkyComparator implements Comparator {
private static Map<String,Integer> orderedExceptions =
new HashMap<String,Integer>(){{
put("PREFZ", Integer.valueOf(1));
put("PREFA", Integer.valueOf(2));
}};
public int compare(Object o1, Object o2) {
String s1 = (String) o1;
String s2 = (String) o2;
Integer i1 = orderedExceptions.get(s1);
Integer i2 = orderedExceptions.get(s2);
if (i1 != null && i2 != null) {
return i1 - i2;
}
if (i1 != null) {
return -1;
}
if (i2 != null) {
return +1;
}
return s1.compareTo(s2);
}
}
Note: This is not the most efficient solution. It is just a simple, straightforward solution that gets the job done.
I would first use Collections.sort(list) to sort the list.
Then, I would remove the known items, and add them to the front.
String special = "PREFA";
if (list.remove(special)
list.add(0, special);
Or, if you have a list of array of these values you need in the front you could do:
String[] knownValues = {};
for (String s: knownValues) {
if (list.remove(s))
list.add(0, s);
}
Since I'm a fan of the guava lib, I wanted to find a solution using it. I don't know if it's efficient, neither if you find it as simple as others solution, but it's here:
final Iterable<String> all = asList("FOO", "BAR", "PREFA", "ZOO", "PREFOO", "PREFZ");
final List<String> mustAppearFirst = asList("PREFZ", "PREFA");
final Iterable<String> sorted =
concat(
Ordering.explicit(mustAppearFirst).sortedCopy(filter(all, in(mustAppearFirst))),
Ordering.<String>natural().sortedCopy(filter(all, not(in(mustAppearFirst)))));
You specifically mentioned guava; along with Sylvain M's answer, here's another way (more as an academic exercise and demonstration of guava's flexibility than anything else)
// List is not efficient here; for large problems, something like SkipList
// is more suitable
private static final List<String> KNOWN_INDEXES = asList("PREFZ", "PREFA");
private static final Function<Object, Integer> POSITION_IN_KNOWN_INDEXES
= new Function<Object, Integer>() {
public Integer apply(Object in) {
int index = KNOWN_INDEXES.indexOf(in);
return index == -1 ? null : index;
}
};
...
List<String> values = asList("FOO", "BAR", "PREFA", "ZOO", "PREFZ", "PREFOO");
Collections.sort(values,
Ordering.natural().nullsLast().onResultOf(POSITION_IN_KNOWN_INDEXES).compound(Ordering.natural())
);
So, in other words, sort on natural order of the Integer returned by List.indexOf(), then break ties with natural order of the object itself.
Messy, perhaps, but fun.
I would also use Collections.sort(list) but I think I would use a Comparator and within the comparator you could define your own rules, e.g.
class MyComparator implements Comparator<String> {
public int compare(String o1, String o2) {
// Now you can define the behaviour for your sorting.
// For example your special cases should always come first,
// but if it is not a special case then just use the normal string comparison.
if (o1.equals(SPECIAL_CASE)) {
// Do something special
}
// etc.
return o1.compareTo(o2);
}
}
Then sort by doing:
Collections.sort(list, new MyComparator());

Categories