Ordering objects in java *without* using values - java

I want to create a class of objects to compare to each other, without using values to compare them with. Is there a library in Java which is able to provide this functionality for me? In terms of ordering, the most frequently mentioned library is Comparator, but all the examples I have seen so far use some kinds of value from the objects in order to perform this ordering with.
For example, I want to be able to say that within a class of objects that:
Object A is more important than Object B.
Object B is more important than Object C.
Therefore, I want the library to be able to perform some kind of analysis, and to be able to order the items according to these values, and say to me, that the order of the values above are A, B, C, in that order.
Is there a library which is able to do this in Java?

Are you thinking of something like this?
enum Importance {
High,
Medium,
Low;
}
class Thing implements Comparable<Thing> {
private Importance importance = Importance.Medium;
public Importance getImportance() {
return importance;
}
public void setImportance(Importance importance) {
this.importance = importance;
}
#Override
public int compareTo(Thing o) {
return importance.compareTo(o.importance);
}
}
Alternatively - if you want to control the relativity of each object then record that in a Map. You will need to be careful to tightly control the map to ensure there are no cycles - if there is then your sorting will become unstable.
static Map<Thing, Set<Thing>> moreImportant = new HashMap<>();
class Thing implements Comparable<Thing> {
#Override
public int compareTo(Thing o) {
Set<Thing> more = moreImportant.get(this);
return more == null ? 0 : more.contains(o) ? 1 : -1;
}
}

Related

Is there a data structure that only stores hash codes and not the actual objects?

My use-case is that I'm looking for a data structure in Java that will let me see if an object with the same hash code is inside (by calling contains()), but I will never need to iterate through the elements or retrieve the actual objects. A HashSet is close, but from my understanding, it still contains references to the actual objects, and that would be a waste of memory since I won't ever need the contents of the actual objects. The best option I can think of is a HashSet of type Integer storing only the hash codes, but I'm wondering if there is a built-in data structure that would accomplish the same thing (and only accept one type as opposed to HashSet of type Integer which will accept the hash code of any object).
A Bloom filter can tell whether an object might be a member, or is definitely not a member. You can control the likelihood of false positives. Each hash value maps to a single bit.
The Guava library provides an implementation in Java.
You could use a primitive collection implementation like IntSet to store values of hash codes. Obviously as others have mentioned this assumes collisions aren't a problem.
If you want to track if a hash code is already present and to do it memory efficient a BitSet may suite your requirements.
Look at the following example:
public static void main(String[] args) {
BitSet hashCodes = new BitSet();
hashCodes.set("1".hashCode());
System.out.println(hashCodes.get("1".hashCode())); // true
System.out.println(hashCodes.get("2".hashCode())); // false
}
The BitSet "implements a vector of bits that grows as needed.". It's a JDK "built-in data structure" which doesn't contain "references to the actual objects". It stores only if "the same hash code is inside".
EDIT:
As #Steve mentioned in his comment the implementation of the BitSet isn't the most memory efficient one. But there are more memory efficient implementations of a bit set - though not built-in.
There is no such built-in data structure, because such a data structure is rarely needed. It's easy to build one, though.
public class HashCodeSet<T> {
private final HashSet<Integer> hashCodes;
public MyHashSet() {
hashCodes = new HashSet<>();
}
public MyHashSet(int initialCapacity) {
hashCodes = new HashSet<>(initialCapacity);
}
public HashCodeSet(HashCodeSet toCopy) {
hashCodes = new HashSet<>(toCopy.hashCodes);
}
public void add(T element) {
hashCodes.add(element.hashCode());
}
public boolean containsHashCodeOf(T element) {
return hashCodes.contains(element.hashCode());
}
#Override
public boolean equals(o: Object) {
return o == this || o instanceof HashCodeSet &&
((HashCodeSet) o).hashCodes.equals(hashCodes);
}
#Override
public int hashCode() {
return hashCodes.hashCode(); // hash-ception
}
#Override
public String toString() {
return hashCodes.toString();
}
}

Implement configurable sort criterias

I need to be able to sort an object by multiple conditions, and these sorts need to be configurable from the application.properties file (as in it should be possible to specify in the file the sorts to apply and the order).
So in my design I created a comparator for each one of the sorts, and then an enum with a supplier such as:
public enum CarSort {
ENGINE(CarEngineComparator::new), BRAND(CarBrandComparator::new);
private final Supplier<Comparator<Car>> constructor;
CarSort(Supplier<Comparator<Car>> constructor){
this.constructor = constructor;
}
Comparator<Car> newComparator() {
return constructor.get();
}
}
With this design, I then would be able to load the sorts from a properties file:
myapp.cars.sorts=BRAND,ENGINE
And chain the sorts with something like:
Stream<Comparator<Car>> comparators = sorts.stream().map(CarSort::newComparator);
return comparators
.reduce(Comparator::thenComparing)
.map(comparator -> filteredCars.sorted((comparator.reversed())))
.orElse(filteredCars)
.collect(Collectors.toList());
The problem I have at the moment is that one of the comparators requires two parameters, so I don't think this solution holds anymore, but I can't think of any clean alternatives at the moment.
Do you know if it would be possible to adapt my current design to fit this requirement, or have any alternative viable solution?
I'm going to add more details. Let's say the specific comparator I need to add sorts cars based for example on how far they are from the client. So it could be something like this (details are not important really, only the fact that it needs an additional parameter):
public class CarDistanceComparator implements Comparator<Car> {
private Location origin;
CarDistanceComparator(Location origin) {
this.origin = origin;
}
#Override
public int compare(Car o1, Car o2) {
double distanceToFirstCar = DistanceService.calculateDistance(origin, o1.getLocation());
double distanceToSecondCar = DistanceService.calculateDistance(origin, o2.getLocation());
return Double.compare(distanceToFirstCar, distanceToSecondCar);
}
}
So then what I would like is to be able to sort by BRAND, ENGINE, DISTANCE (as specified in the config file) for multiple customers. Meaning that I would need to pass a different argument each time to the DistanceComparator.

Custom hashmap with 2 value fields VS implement a hashmap with an array as value in java

Are they added benefits to writing my own hash map data structure instead of using a pre written class like hashmap in java.
Background.
Im writing a spring application that requires data structure that can map a single key to map to two values.
the current benefits i can think of now will be:
- can include more methods such as swap (swap value 1 with 2)
- more control over hashing functions
- more control in general
was wondering:
- if they are any draw backs in terms of performance or complexity
- or if it makes any sense at all to write my own data structure
Thanks for taking the time to read.
EDIT:
If it helps helps.
i only need fast access speed (methods like get and contains)
for methods that "put", time taken can be a little longer
Any suggestion on what i should do?
Keep it simple: Use HashMap whose value type is a simple class to hold two values, eg (for simplicity, I have assumed key and both values are String):
class Pair {
private String a;
private String b;
public Pair(String a, String b) {
this.a = a;
this.b = b;
}
public String getA() {
return a;
}
public String getB() {
return b;
}
public void swap() {
// Note: Not threadsafe
String tmp = a;
a = b;
b = tmp;
}
public boolean equals(Object o) {
return o instanceof Pair
&& Objects.equals(a, ((Pair)o).a
&& Objects.equals(b, ((Pair)o).b;
}
public int hashCode() {
return Objects.hash(a, b);
}
}
Map<String, Pair> map = new HashMap<>();
You risk missing out on a very well-vetted, proven and durable framework by not using the java.util package. No offense, but it's unlikely you're going to come up with a better design and implementation, especially one as bug-free and optimized as part of Java's core API. Rather, use what exists and either write your own small methods, extend the existing HashMap, or find another open-source variant (e.g. maybe from Apache FastHashMap) to get the additional required functionality.

Non static comparator inner class

I would like to know is it ok to make non static inner class which implements comparator interface.
eg.
public class A {
private Map<String, Integer> scoreMap;
private final class myComparator implements Comparator<MyOtherClass> {
private int calScore(MyOtherClass ob) {
int score = ob.someValue * ob.otherValue;
scoreMap.put(ob.getName(), score);
}
public int compare(MyOtherClass ob1, MyOtherCLass ob2) {
return Integer.compare(calScore(ob1), calScore(ob2));
}
}
}
I would like to use comparator class non static because I want to use non static field "num" and want to modify its value. Is it fine to have non static comparator inner class?
Additional Info
For each object I am calculating score inside compare and sorting accordingly. I need to save those scores in a map which I calculated inside comparator and want to use this map in outer class for further calculation.
Technically nothing is stopping you. Morally however...
As long as you maintain the idempotency (run multiple times and get same result) then it is not incorrect. However it is a sideeffect. (use this comparator, and some class's values change. run another comparator and nothing changes). Side effects aren't necessarily bad but they make a program more complex and harder to understand and debug.
Try seeing it through the eyes of some poor soul that has to maintain your code. Some value changes and they have no idea why. all they did was compare an unaffiliated list.
anyways your example is very abstract so it's hard to judge the context but usually there is no need to do what you want to do. It is generally something to be avoided unless you have a really good reason for it. And that really good reason shouldn't be "because I don't want to loop over the dataset again" in my opinion.
from your edit:
You are trying to save yourself work by not having to do the recalculating again from the sounds of it. You're saving yourself only a small amount of effort really. why not first calculate the scores, store the result, then sort the results (on score field)
like:
public static class ScoredEntry {
private SomeGameData data; //or something
private int score;
// constructor takes data + score, imagine getters, setters, I am lazy ok.
}
public List<ScoredEntry> scoreEntries(List<SomeGameData> gameData) {
List<ScoredEntry> result = new ArrayList<ScoredEntry>();
for (SomeGameData data : gameData) {
int score = calculateScore(data);
result.add(new SCoredEntry(score, data);
}
return result;
}
public void sortBySCore(List<ScoredEntry> list) {
Collections.sort(list, new Comparator<ScoredEntry>() {
public int compare(SCoredEntry a, ScoredEntry b) {
// etcetera.
}
}
}

Most efficient way to see if an ArrayList contains an object in Java

I have an ArrayList of objects in Java. The objects have four fields, two of which I'd use to consider the object equal to another. I'm looking for the most efficient way, given those two fields, to see if the array contains that object.
The wrench is that these classes are generated based on XSD objects, so I can't modify the classes themselves to overwrite the .equals.
Is there any better way than just looping through and manually comparing the two fields for each object and then breaking when found? That just seems so messy, looking for a better way.
Edit: the ArrayList comes from a SOAP response that is unmarshalled into objects.
It depends on how efficient you need things to be. Simply iterating over the list looking for the element which satisfies a certain condition is O(n), but so is ArrayList.Contains if you could implement the Equals method. If you're not doing this in loops or inner loops this approach is probably just fine.
If you really need very efficient look-up speeds at all cost, you'll need to do two things:
Work around the fact that the class
is generated: Write an adapter class which
can wrap the generated class and
which implement equals() based
on those two fields (assuming they
are public). Don't forget to also
implement hashCode() (*)
Wrap each object with that adapter and
put it in a HashSet.
HashSet.contains() has constant
access time, i.e. O(1) instead of O(n).
Of course, building this HashSet still has a O(n) cost. You are only going to gain anything if the cost of building the HashSet is negligible compared to the total cost of all the contains() checks that you need to do. Trying to build a list without duplicates is such a case.
*
() Implementing hashCode() is best done by XOR'ing (^ operator) the hashCodes of the same fields you are using for the equals implementation (but multiply by 31 to reduce the chance of the XOR yielding 0)
You could use a Comparator with Java's built-in methods for sorting and binary search. Suppose you have a class like this, where a and b are the fields you want to use for sorting:
class Thing { String a, b, c, d; }
You would define your Comparator:
Comparator<Thing> comparator = new Comparator<Thing>() {
public int compare(Thing o1, Thing o2) {
if (o1.a.equals(o2.a)) {
return o1.b.compareTo(o2.b);
}
return o1.a.compareTo(o2.a);
}
};
Then sort your list:
Collections.sort(list, comparator);
And finally do the binary search:
int i = Collections.binarySearch(list, thingToFind, comparator);
Given your constraints, you're stuck with brute force search (or creating an index if the search will be repeated). Can you elaborate any on how the ArrayList is generated--perhaps there is some wiggle room there.
If all you're looking for is prettier code, consider using the Apache Commons Collections classes, in particular CollectionUtils.find(), for ready-made syntactic sugar:
ArrayList haystack = // ...
final Object needleField1 = // ...
final Object needleField2 = // ...
Object found = CollectionUtils.find(haystack, new Predicate() {
public boolean evaluate(Object input) {
return needleField1.equals(input.field1) &&
needleField2.equals(input.field2);
}
});
If the list is sorted, you can use a binary search. If not, then there is no better way.
If you're doing this a lot, it would almost certainly be worth your while to sort the list the first time. Since you can't modify the classes, you would have to use a Comparator to do the sorting and searching.
Even if the equals method were comparing those two fields, then logically, it would be just the same code as you doing it manually. OK, it might be "messy", but it's still the correct answer
If you are a user of my ForEach DSL, it can be done with a Detect query.
Foo foo = ...
Detect<Foo> query = Detect.from(list);
for (Detect<Foo> each: query)
each.yield = each.element.a == foo.a && each.element.b == foo.b;
return query.result();
Is there any better way than just looping through and manually comparing the two fields for each object and then breaking when found? That just seems so messy, looking for a better way.
If your concern is maintainability you could do what Fabian Steeg suggest ( that's what I would do ) although it probably isn't the "most efficient" ( because you have to sort the array first and then perform the binary search ) but certainly the cleanest and better option.
If you're really concerned with efficiency, you can create a custom List implementation that uses the field in your object as the hash and use a HashMap as storage. But probably this would be too much.
Then you have to change the place where you fill the data from ArrayList to YourCustomList.
Like:
List list = new ArrayList();
fillFromSoap( list );
To:
List list = new MyCustomSpecialList();
fillFromSoap( list );
The implementation would be something like the following:
class MyCustomSpecialList extends AbstractList {
private Map<Integer, YourObject> internalMap;
public boolean add( YourObject o ) {
internalMap.put( o.getThatFieldYouKnow(), o );
}
public boolean contains( YourObject o ) {
return internalMap.containsKey( o.getThatFieldYouKnow() );
}
}
Pretty much like a HashSet, the problem here is the HashSet relies on the good implementation of the hashCode method, which probably you don't have. Instead you use as the hash "that field you know" which is the one that makes one object equals to the other.
Of course implementing a List from the scratch lot more tricky than my snippet above, that's why I say the Fabian Steeg suggestion would be better and easier to implement ( although something like this would be more efficient )
Tell us what you did at the end.
Maybe a List isn't what you need.
Maybe a TreeSet would be a better container. You get O(log N) insertion and retrieval, and ordered iteration (but won't allow duplicates).
LinkedHashMap might be even better for your use case, check that out too.
Building a HashMap of these objects based on the field value as a key could be worthwhile from the performance perspective, e.g. populate Maps once and find objects very efficiently
If you need to search many time in the same list, it may pay off to build an index.
Iterate once through, and build a HashMap with the equals value you are looking for as the key and the appropriate node as the value. If you need all instead of anyone of a given equals value, then let the map have a value type of list and build the whole list in the initial iteration.
Please note that you should measure before doing this as the overhead of building the index may overshadow just traversing until the expected node is found.
There are three basic options:
1) If retrieval performance is paramount and it is practical to do so, use a form of hash table built once (and altered as/if the List changes).
2) If the List is conveniently sorted or it is practical to sort it and O(log n) retrieval is sufficient, sort and search.
3) If O(n) retrieval is fast enough or if it is impractical to manipulate/maintain the data structure or an alternate, iterate over the List.
Before writing code more complex than a simple iteration over the List, it is worth thinking through some questions.
Why is something different needed? (Time) performance? Elegance? Maintainability? Reuse? All of these are okay reasons, apart or together, but they influence the solution.
How much control do you have over the data structure in question? Can you influence how it is built? Managed later?
What is the life cycle of the data structure (and underlying objects)? Is it built up all at once and never changed, or highly dynamic? Can your code monitor (or even alter) its life cycle?
Are there other important constraints, such as memory footprint? Does information about duplicates matter? Etc.
I would say the simplest solution would be to wrap the object and delegate the contains call to a collection of the wrapped class. This is similar to the comparator but doesn't force you to sort the resulting collection, you can simply use ArrayList.contains().
public class Widget {
private String name;
private String desc;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
public abstract class EqualsHashcodeEnforcer<T> {
protected T wrapped;
public T getWrappedObject() {
return wrapped;
}
#Override
public boolean equals(Object obj) {
return equalsDelegate(obj);
}
#Override
public int hashCode() {
return hashCodeDelegate();
}
protected abstract boolean equalsDelegate(Object obj);
protected abstract int hashCodeDelegate();
}
public class WrappedWidget extends EqualsHashcodeEnforcer<Widget> {
#Override
protected boolean equalsDelegate(Object obj) {
if (obj == null) {
return false;
}
if (obj == getWrappedObject()) {
return true;
}
if (obj.getClass() != getWrappedObject().getClass()) {
return false;
}
Widget rhs = (Widget) obj;
return new EqualsBuilder().append(getWrappedObject().getName(),
rhs.getName()).append(getWrappedObject().getDesc(),
rhs.getDesc()).isEquals();
}
#Override
protected int hashCodeDelegate() {
return new HashCodeBuilder(121, 991).append(
getWrappedObject().getName()).append(
getWrappedObject().getDesc()).toHashCode();
}
}

Categories