Using a Set with one Class but find with a String - java

I have a Java Set<MyClass> on which I've overridden equals and hashCode to use the String name; variable.
public class MyClass{
final String name;
public boolean equals(Object o){...}
public int hashCode(){return name.hashCode();}
}
Is there anyway I can get my Object out of the HashSet using something like
MyClass o = set.get("nameofmyobject");
Is there a way to do this in Java, or a datastructure? or do I need to change up all of my Sets to Maps?

No. You need to change to a Map. None of the methods of Set return an element.
Addendum A
If you don't care about speed you can always search manually:
MyClass find(String name, Set<MyClass> set)
{
MyClass wrapper = new MyClass(name);
for (MyClass e : set) {
if (wrapper.equals(e)) {
return e;
}
}
return null;
}
Addendum B
If you use a TreeSet you can use floor:
MyClass find(String name, TreeSet<MyClass> set)
{
MyClass wrapper = new MyClass(name);
MyClass candidate = set.floor(wrapper);
if (candidate != null && wrapper.equals(candidate)) {
return candidate;
} else {
return null;
}
}

Have a look at this question. The answer is no. Sets are not for getting elements, but to look for equality. Use a Map or List insteed.

As Tim said you can't. And if so you would have to call it like set.get(myClassInstance); and not set.get(some member of the stored instance)
Use
Map<String, MyClass> myMap = new HashMap<String, MyClass>();

Related

Method to accept any Enum and return all properties

I have the following Enum where I would like to create a method that will accept an Enum object, and return a comma separated list of the properties of that Enum. So for the following Enum, my method would accept it as a parameter and return a String of "1, 2".
public class typeEnum {
public enum validTypes{
TYPE1("1"),
TYPE2("2");
private String value;
validTypes(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public static boolean contains(String type) {
for (validTypes msgType : validTypes.values()) {
if (msgType.value.equals(type)) {
return true;
}
}
return false;
}
}
}
My expected method would be something like the following:
public static <E extends Enum<E>, S extends String> String enumPropsToString(E enumClazz, S value) {
return ....
}
Enums can implement interfaces:
public interface ValuedEnum {
public String getValue();
}
public class SomeEnum implements ValuedEnum {
//your body from above
}
Then, you can use "intersection types" in your method signature:
public <T extends Enum<T> & ValuedEnum> String propsToString (Class<T> enumClass) {
Arrays.stream(enumClass.getEnumConstants()).map(e -> e.getValue()).collect(Collectors.joining(", "));
}
You could also do this via reflection - inspect the enumClass parameter of an arbitrary Enum for a Method with the getValue signature you want, and then reflectively call it; but this way is type-safe and sufficiently trivial that I'd strongly recommend doing this instead.
Reading your comments, if you want to allow an arbitrary property, then I'd suggest just using the Stream API:
public static <T> String propsToString (T[] values, Function<T, String> extractor) {
return Arrays.stream(values).map(extractor).collect(Collectors.joining(", "));
}
which can be invoked like this:
propsToString(MyEnum.values(), MyEnum::name);
Here is the method you need:
private static <E extends Enum<E>> String enumValues(Class<E> clazz) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Method m = clazz.getMethod("values");
Object[] values = (Object[])m.invoke(null);
Method f = clazz.getMethod("getValue");
StringBuilder sb = new StringBuilder(f.invoke(values[0]).toString());
for (int i = 1 ; i < values.length ; i++) {
sb.append(", ");
sb.append(f.invoke(values[i]).toString());
}
return sb.toString();
}
Usage:
enum MyEnum {
X("A"), Y("B");
public String value;
MyEnum(String value) {
this.value = value;
}
}
// ...
System.out.println(enumValues(MyEnum.class));
// prints "A, B"
Explanation of how this works:
Instead of passing an enum instance to the method, you should pass a Class<E>. This makes it easier for reflecting stuff from it. It also makes it easier to call the method as you don't need to create a new enum instance.
First, we need to get all the values of the enum class passed in. To do this we get the method values from the enum class and call it. Here I stored all the values in a variable called values.
I then got the method getValue from the enum class. In the comments you said that when an enum does not have a value field it should not be passed into this method. I assume you mean you don't care about non-existent value fields and you trust the caller. That's why I didn't do any checks here.
After that I used a string builder and for loop to concatenate the value of value for each of the enum values.
Phew that was long!
Note that this method is extremely unsafe. You should probably use interfaces like the other answers have said. But hey, this is fun, and you seem confident that you won't pass anything invalid in there. :)

Get return statements in a java method

How can I get all possible return values of a method in java?
Example:
Object onEvent() {
if (condition) {
return "a";
}
if (condition2) {
return "b";
}
if (condition3) {
return "c";
}
}
I need something like this:
String[] returns = Utils.getReturnStatements("object.onEvent()");
returns = ["a", "b", "c"]
You can only retrieve the method signature, which in this case would be Object as the return type.
To get the any more details you need to either statically analyze the source code or return a type such as an enum.
If you only need to analyse simple methods that return constant values such as the one in your example, then you can do this relatively easily via a static analysis using ASM or a similar bytecode toolkit.
For methods matching the structure of your example (i.e that only directly return constants) you just need to look for the pattern
LDC ???
ARETURN
And collect the constants loaded with LDC. This would be very straightforward.
If the methods can be more complex, e.g if they return values assigned to variables, then you will need to perform a flow analysis. This is much more work, but ASM provides support.
If the methods you are analysing return values other than simple constants then it will be incredibly difficult/impossible to do this via static analysis.
You can't do such a thing in Java, but you can do something like this:
Object onEvent() {
List<String> list = new ArrayList<String>();
if (condition) {
list.add("a");
}
if (condition2) {
list.add("b");
}
if (condition3) {
list.add("c");
}
return list.toArray();
}
And then:
String[] returns = (String[])MyObj.onEvent();
First remove multiple returns:
Also to get all return types just pass a List of object to your method and change the onEvent code like this:
Object onEvent(List<Object> rets) {
String ret = "";
rets.add("a");
rets.add("b");
rets.add("c");
if (condition) {
ret = "a";
}
if (condition2) {
ret = "b";
}
if (condition3) {
ret = "c";
}
return ret;
}
Make a call to onEvent like this:
List<Object> returns = new ArrayList<Object>();
Object retVal = obj.onEvent(returns);
As #Johan said, it is not possible. The only way if you really need it would be for you to store these possible results in a Map mapping the method name to a List or array, or better, use an enum if possible.
Edit:
After reading your comment, I think you should use a HashMap with a Node as the key and a List as value. When you analyse a Node you create the list of exit Nodes in a list, and then map that list to the node.
With use of the command pattern and enum there is a workaround.
public class OnEvent implements Command<EventInfo> {
#Override
public EventInfo execute() {
// do some checking
return EventInfo.A;
}
#Override
public EventInfo[] getValues() {
return EventInfo.values();
}
public static void main(String[] args) {
OnEvent e = new OnEvent();
EventInfo retVal = e.execute();
EventInfo[] values = Utils.getReturnStatements(e);
}
}
enum EventInfo {
A, B, C;
}
interface Command<TYPE extends Enum<?>> extends KnownReturnValues<TYPE> { public TYPE execute(); }
interface KnownReturnValues<TYPE> { public TYPE[] getValues(); }
class Utils {
private Utils() {}
public static <TYPE extends Enum<?>> TYPE[] getReturnStatements(Command<TYPE> c) {
return c.getValues();
}
}
Its not really good programming practice, but you can create a class with 3 public data members, and have your code look something like this. (Ill call the class "myclass")
public a, b, c = null;
//And then your main class would look something like this
if (condition){
myclass.a=whatever;
}
else if (condition){
myclass.b=whatever;
}
else if (condition){
myclass.c=whatever
}
Then you would need another control structure that said something along the lines of
if (myclass.datamember!=null) to make sure you have values in the class data members. Again, this is not good programming practice, but it will work for what you want.

How to create a static 'Object Holder' class using generics in Java

I am trying to create an object holder util class to be short.
Forexample;
public ResponseAbc bringMeStuff(RequestAbc request){
ResponseAbc response = new ResponseAbc();
/* Setting request here.. */
response = bringMeLotsOfStuff(request);
/* Here I am calling the Util class */
Util.putToObjectHolder("myAbcResponse", response);
return response;
}
public void testMe(){
/* Testing objectHolder */
ResponseAbc newResponse = (ResponseAbc) Util.getFromObjectHolder("response");
}
Here is the Util class
public class Util<T> {
private static Util<?> instance = null;
private Map<String, T> objHolder;
private Util() {
}
/* I strongly think Util class should be singleton if I want to hold the map globally */
public static Util<?> getInstance() {
if (instance == null) {
instance = new Util();
}
return instance;
}
public static <T> void putToObjectHolder(String objectName, T objectType) {
// Map<String, T> holder = (Map<String, T>) getInstance().getObjHolder();
// holder.put(objectName, objectType);
getInstance().getObjHolder().put(objectName, objectType); //-> Argument error
}
public static <T> Object getFromObjectHolder(final String objectName) {
Map<String, T> holder = (Map<String, T>) getInstance().getObjHolder();
T obj = null;
for (Entry<String, T> entry : holder.entrySet()) {
if (entry.getKey().equals(objectName)) {
obj = entry.getValue();
} else {
obj = null;
}
}
return obj;
}
public Map<String, T> getObjHolder() {
if (objHolder == null) {
objHolder = new HashMap<String, T>();
}
return objHolder;
}
public void setObjHolder(Map<String, T> objHolder) {
this.objHolder = objHolder;
}
}
If I uncomment putToObjectHolder method, it works but I am not pretty sure it supposed to work that way. I mean creating an other map and assigning to it should do the trick.
What I intent to do is holding a static Map holder with single instance so I can put whatever object I want with a name and get that object whenever I want if it exist in that 'global holder'.
PS: It is pretty messy with type safety warnings for sure, I would love to improve that aswell though I am not sure how to.
Thanks in advance.
Putting aside the singleton part, are you trying to use generics to get objects (of varying types) into and out of the same Map whilst retaining type safety? That is, if you put into the map (for a given key) say a String then getting this value out will only compile if it is assigned to (or used as) a string. (And, also, there are no casts in the code.)
This can be done but it is a bit involved as you need to define keys that have the type of the corresponding value.
See: Java map with values limited by key's type parameter
Joshua Block also had a good article on this somewhere but I don't seem to be able to find it.
This seems to be what you are trying to achieve with your put method. You won't be able to do it with strings as keys though - you'll need a genericized, typed key.
You are not using generic the way they are meant to be used. Take a look at the ArrayList class to learn the true potential of generics.
Also singleton of this class serves no purpose as you only need a "singleton" of a HashMap.
Maybe I do not see what you are trying to accomplish but this is essentially what you are trying to do. Why don't you just use a HashMap and be done with it?
import java.util.HashMap;
public class Util {
private static HashMap<String, Object> values = new HashMap<String, Object>;
private Util() {
}
public static void put(String key, Object value) {
values.put(key, value);
}
public static Object get(String key) {
return values.get(key);
}
public static void main(String[] args) {
String s = "This is a test.";
Util.put("test", s);
System.out.println(Util.get("test"));
System.out.println(Util.get("another test"));
}
}

Substitution for generic type's field

I have generic structure and I need to search using various generic type's attributes.
Let's think of following implementation:
public class Person {
private int id;
private String name;
// + getters & setters
}
Now I have my custom data structure and one of it's method is like:
public T search(T data) { ... }
That is nonsense of course. What I really need in code is something like:
Person p = structure.search(12); // person's id
or
Person p = structure.search("Chuck N."); // person's name
So in pseudoJava (:)) the code would be something like this:
public T search(T.field key)
This isn't possible of course :( But how can one deal with this kind of situation? The point is: I don't want to force client's classes (like Person) to implement my own interface or to extend my own class. Is there any workaround?
Looks like you want some kind of intermediary strategy object, that extracts a value, compares a value, perhaps supplies a hash code or a comparison function.
Something like:
interface Matcher<T> {
boolean matches(T obj);
}
or methods such as:
boolean matches(T obj, V value);
V get(T obj);
int hash(T obj);
int compare(T a, T b);
Use is somewhat verbose with the current Java syntax (may change for JDK 8).
You'll end up with something like this:
Person p = structure.search(
new Matcher<Person>() { public boolean matches(Person person) {
return person.getID() == 12;
})
);
or:
Person p = structure.search(
new Matcher<Person,Integer>() {
public boolean matches(Person person, Integer id) {
return person.getID() == id;
}
),
12
);
In JDK8, perhaps something like:
Person p = structure.search(
{ Person person -> person.getID() == 12 }
);
or:
Person p = structure.search(
{ Person person, Integer id -> person.getID() == id },
12
);
or:
Person p = structure.search(
{ Person person -> person.getID() },
12
);
or:
Person p = structure.search(
Person#getID, 12
);
You could make the signature of search contain the type parameter by adding a Class parameter. As an example:
//replace 'id' with whatever your identifier types are
public <T> T search(int id, Class<T> entityClass) { ... }
Clients would then have to use the method like
Person p = foo.search(123, Person.class);
NotAPerson n = foo.search(234, NotAPerson.class);
It might look a little ugly to have to include the class, but when you really think about things - doesn't the client always know what it is searching for? And doesn't the code behind search() need to know which type to be searching for - what if you have IDs that are shared by different types?
If your IDs are not of a consistent type, you could change the signature to
public <T> T search(Serializable id, Class<T> entityClass) { ... }
I'd suggest you to use Comparable interface.
Person p = structure.searchUnique(new FieldFilter("id", 12)); // searches for person with id 12
Person[] p = structure.searchAll(new FieldFilter("name", "John")); // searches for person named John
Moreover we can implement filter that allows to search over all available fields of the target class:
Person[] p = structure.searchAll(new FieldFilter("John")); // searches for all Johns
How to implement this? Here are some tips.
First what the "structure" is? It is a wrapper over collection that may probably contain some indexing functionality in future. This class should have constructor like
Structure(Collection data);
Its search method iterates over given collection and calls compateTo() method of FieldFilter that implements Comparable:
for (T elem : collection) {
if (filter.compareTo(elem)) {
result.add(elem);
}
}
return result;
The FieldFilter should look like:
public class FieldFilter implements Comparable {
private String fieldName;
private V fieldValue;
public FieldFilter(String fieldName, V fieldValue) {
this.fieldName = fieldName;
this.fieldValue = fieldValue;
}
public boolean compareTo(T elem) {
Field field = elem.getClass().getField(fieldName);
field.setAccessible(true);
return field.getValue().equals(fieldValue);
}
}
Please note that the code was written directly in answer form, was never compiled, so it cannot be used as is. But I hope it describes the idea.
If you want to enforce a mapping through generics between the type being searched for, and the parameter-type passed to the search() method, you have to specify this somewhere. I don't think there's any way to do this without at least a generic marker interface for the client's classes.
Something like this would work for example:
public interface Searchable<T> { }
public class Person implements Searchable<String> {
// ...
}
public <T extends Searchable<K>, K> T search(K key) {
// ...
}
So now the compiler will allow:
Person p = search("John Doe");
but not:
Person p = search(5);
If even a marker interface is not an option, I'm afraid the best you can hope for is to use specific search methods based on the parameter type, like:
public <T> T searchByInt(int key) {
// ...
}
public <T> T searchByString(String key) {
// ...
}
but of course this will mean invalid cases like
Person p = searchByInt(5);
won't be caught at compile-time, but rather will need to be checked for at runtime instead.

Using two (or more) objects as a HashMap key

I want to store certain objects in a HashMap. The problem is, usually you just use a single object as a key. (You can, for example, use a String.) What I want to do it to use multiple object. For example, a Class and a String. Is there a simple and clean way to implement that?
You key must implement the hashCode and equals. If it is a SortedMap, it must also implements the Comparable interface
public class MyKey implements Comparable<MyKey>
{
private Integer i;
private String s;
public MyKey(Integer i,String s)
{
this.i=i;
this.s=s;
}
public Integer getI() { return i;}
public String getS() { return s;}
#Override
public int hashcode()
{
return i.hashcode()+31*s.hashcode();
}
#Override
public boolean equals(Object o)
{
if(o==this) return true;
if(o==null || !(o instanceof MyKey)) return false;
MyKey cp= MyKey.class.cast(o);
return i.equals(cp.i) && s.equals(cp.s);
}
public int compareTo(MyKey cp)
{
if(cp==this) return 0;
int i= i.compareTo(cp.i);
if(i!=0) return i;
return s.compareTo(cp.s);
}
#Override
public String toString()
{
return "("+i+";"+s+")";
}
}
public Map<MyKey,String> map= new HashMap<MyKey,String>();
map.put(new MyKey(1,"Hello"),"world");
I tend to use a list
map.put(Arrays.asList(keyClass, keyString), value)
The easiest way that I know of is to make a wrapper class and override hashmap and equals. For instance:
public class KeyClass {
private String element1;
private String element2;
//boilerplate code here
#Override
public boolean equals(Object obj) {
if (obj instanceof KeyClass) {
return element1.equals(((KeyClass)obj).element1) &&
element2.equals(((KeyClass)obj).element2);
}
return false;
}
#Override
public int hashCode() {
return (element1 + element2).hashcode();
}
}
OF course, I would recommend using a StringBuilder and whatever else, but this way you have overridden the equals and hashcode, thereby allowing a hash and equality check on your multiple keys.
Also, I would recommend making the objects immutable (not editable) for safety's sake, but that is purely preference.
Apache Commons Collections has a multikey map which might do the trick for you:
https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/keyvalue/MultiKey.html
It looks like it will handle up to 5 "keys".
Do you mean that the object will be keyed by two keys, or rather a key which consists of two things.
If you want the first case. That is, an objected keyed by two keys, say a class or an object, you need to use two maps.
Map<Key1, value>
Map<Key2, value>
In the second case you need a map of maps, so:
Map<Key1, Map<Key2, value>>
You could create a holder class that contains the class and string that you want as the keys.
public class Key {
public MyClass key_class;
public String key_string;
public Key(){
key_class = new MyClass();
key_string = "";
}
}
Probably not the best solution, but a possibility.
There are a few places where people suggest creating a "Key" class containing the others, I totally agree. Just thought I'd add a helpful hint.
If you use eclipse or netbeans, they have a nice option--you can tell Eclipse to create equals and hashcode methods based on one or more members. So you just select the member (or members) you want to retrieve by and NB creates most of the code you'd need to write for you.
of course when I just want to retrieve by one object, I often just delegate the hashcode and equals methods to that object (delegating equals might be problematic because it would mean that one of your "Key holder" classes would be equal to the object that is it's key, but that's pretty easily fixed (and wouldn't usually effect anything anyway)
so off the top of my head:
class KeyHolder {
public final String key;
public final Object storeMe;
public KeyHolder(String key, Object storeMe) {
this.key=key;
this.storeMe=storeMe;
}
public equals(Object o) {
return (o instanceof KeyHolder && ((KeyHolder)o).key.equals(key));
}
public hashcode() {
return key.hashCode();
}
}
That's all there is to it, and eclipse will do the last two for you if you ask it to.
By the way, I know that I have public members, a public final member is exactly the same thing as having a getter--not really a terrible idea. I'm starting to use this pattern on small utility classes like this a lot more lately. If the member wasn't final, it would be worse because it would be like having a setter (Something I try to avoid these days).
One can solve this issue using apache's commons collection lib's MultiKey class.
Here is a simple example:
import org.apache.commons.collections.keyvalue.MultiKey;
HashMap map = new HashMap();
MultiKey multiKey = new MultiKey(key1, key2);
map.put(multikey,value);
//to get
map.get(new MultiKey(key1,key2));

Categories