I am looking for a nice way to group a list of objects by multiple class attributes. The Google guava library provides a feature to group by a single attribute. I haven't found a utility yet that offers what I am looking for.
See below. I have encapsulated the grouping attributes into its own class Grouping. However, this need not be necessary if a better solution exists.
A class that contains grouping attributes.
Class Grouping{
private String key1;
private String key2;
private String key3;
//getters, setters
}
Class representing a type that would need to be grouped.
Class Groupable{
private Grouping grouping;
private String x;
private String y;
private String z;
// getters, setters
}
What I need is a Map that contains as key, a Groupable object with unique set of keys. And a list of Groupable objects as corresponding grouped items.
Map<Grouping, List<Groupable>> groupings;
Any and all suggestions welcome!
Answering my own question based on #JBNizet and #JohnBollinger's comments.
I use Eclipse IDE, so all I needed to do is to go to Source -> 'Generate hashCode() and equals()..' and invoke the same on my Grouping class to include all attributes in the overridden implementation. There on, guava library can be used in its regular way as below:
Function<Groupable, Grouping> groupFunction = new Function<Groupable, Grouping>(){
#Override
public Grouping apply(Groupable groupable) {
return groupable.getGrouping();
}
};
ImmutableListMultimap<Grouping, Groupable> groupings = Multimaps.index(lsGroupable, groupFunction);
groupings gives me what I need. lsGroupable is a list of Groupable objects.
Related
I have a collection of objects that look something like
class Widget {
String name;
int id;
// Intuitive constructor omitted
}
Sometimes I want to look up an item by name, and sometime I want to look it up by id. I can obviously do this by
Map<String, Widget> mapByName;
Map<Integer, Widget> mapById;
However, that requires maintaining two maps, and at some point, I will (or another user who is unfamiliar with the double map) will make a change to the code and only update one of the maps.
The obvious solution is to make a class to manage the two maps. Does such a class already exist, probably in a third party package?
I am looking for something that lets me do something along the lines of
DoubleMap<String, Integer, Widget> map = new DoubleMap<>();
Widget w = new Widget(3, "foo");
map.put(w.id, w.name, w);
map.get1(3); // returns w
map.get2("foo"); // returns w
A simple solution could be, to write your own key class that includes both keys.
class WidgetKey {
String id;
String name;
boolean equals() {...}
boolean hashCode() {...}
}
Map<WidgetKey, Widget> yourMap;
Beware that you have to implement equals and hashCode in the WidgetKey class. Otherwise put/get and other map methods wouldn't work properly.
This topic is a little bit more complicated then in a title.
Let's assume that we want to model an entity. This is something like KYC informations (name,surname, address etc). I could model this in simple way in one class like:
public class KYCInfo {
private KYCInfoType type;
private String firstName;
private String lastName;
private Address personalAddress;
private Address buisnessAddress;
private String country;
private String state;
private LocalDate dateOfBirth;
private String personalIdNumber;
}
As you see in code above, this KYC can be of different type. Actually two values can be in that type - buisness and individual. For business, buisnessAddress field is required, for individual personalIdNumber is required. Additionaly some of this fields will be required depending on country field. State field is for US but not for European countries. Placing all of this fields in one class seems to be inappropriate - every instance, depending on field would have a lot of null values. I could create separate classes for BuisnessKYCInfo and IndividualKYCInfo for example. But then I would have some duplications in fields (lets say that firstName,lastName and some other fields are the same for both classes). I could create some abstraction with common fields. Like :
public abstract class KYCInfo {
private String firstName;
private String lastName;
}
Now imagine that this is a simple DTO class and in some moment i process it somehow in a method processKYCInfo(). When I have two classes BuisnessKYCInfoandIndividualKYCInfothen I would need to have two methods
``processKYCInfo(BuisnessKYCInfo kycInfo) and processKYCInfo(IndividualKYCInfo kycInfo). This method will do the same operation, but will collect info from different fields. Now imagine, that you have more type than individual or buissness. Or as i wrote before, additional 'type' comes in like country. Now I would need to have 25 countries, some of them have fields specific only for that country. With the same approach like before I would have 25 methods doing almost the same. This also seems to be inappropriate. What other option do I have to model this ? Maybe some data structure, maybe some Map ? What is best approach of doing this ? How can I do it in more generic way ?
Here is my approach:
Following is the data structure I'll use:-
public class KYCInfo {
private KYCInfoType type;
private Map<String, String> name;
private Map<String, String> address;
private String country;
private String state;
private LocalDate dateOfBirth;
private String personalIdNumber;
public KYCInfo(){
name = new HashMap<>();
address = new HashMap<>();
}
So what is the advantage of this approach:-
Instead of creating multiple same type of attributes, create a family. e.g. name will be the family for 'firstName', 'middleName', 'lastName'. The pair will be like <'firstName','Bob'> ,<'lastName','Marley'> etc. In this way you can have either of them or all of them.
Similarly for other attributes like address. The pair can be like <'personalAddress','some value'> , <'buisnessAddress','some value'>
Each record can have their own categories for a family.
I am relatively new to Java. I have been struggling to define a class that meets my needs. Searching on this site or google did not have probably because the question is so specific. Any help is appreciated!
Ideally the class (lets call it Filer) would have:
Name (string)
Volumes (Collection/list of Strings: 0 -100)
Each Volume, in turn, will have:
A. Name (string)
B. Servers_Permed (another collection/list of Strings: 0-40)
Once I can get the class defined, I will do ok with defining getters and setters to use it, but so far I have failed to defined the class without getting totally lost :-)
Thanks!
It seams that your description is not correct.
You need a class Filer with:
name (String)
volumes (list of Volume) (not strings as you asked, because you explained differently on the second part of the question, it is evident that you need a list of Volume and not a list of String)
And a second class Volume with:
Name (string)
Servers_Permed (list of strings)
So you need a data structure like the following:
public class Volume {
private String name;
private List<String> serversPermed; // Changed the name to a name more adherent to standard guidelines
...
}
public class Filer {
private String name;
private List<Volume> volumes;
...
}
well, lay it out piece by piece.
First, you have Volume (not sure how volumes could be "Collection/list of Strings: 0 -100" and have the following properties):
public class Volume {
String name;
List<String> servers_permed;
}
Now you have Filer:
public class Filer {
String name;
List<Volume> volumes;
}
you will have to add the necessary constructors, getters/setters.
Both of the answer given above worked beautifully (they are almost the same anyway).
Thank you, Davide and DBug!
I'm a java beginner and have a question concerning how to best structure a cooking program.
I have a class called Ingredient, this class currently looks like this:
public class Ingredient {
private String identifier;
private double ingredientFactor;
private String titleInterface;
public Ingredient(String identifier, double ingredientFactor,String titleInterface) {
this.identifier = identifier;
this.ingredientFactor = ingredientFactor;
this.titleInterface = titleInterface;
}
I want to initialize several objects (about 40) with certain values as instance variables and save them in a Map, for example
Map<String, Ingredient> allIngredients = new HashMap<String, Ingredient>();
allIngredients.put("Almonds (ground)", new Ingredient("Almonds (ground)", 0.7185, "Almonds (ground)");
Later on I want to retrieve all these objects in the form of a Map/HashMap in a different class.
I'm not sure how to proceed best, initialize all these objects in the Ingredient class itself or provide a method that initializes it or would it be better to create an super class (AllIngredients or something like that?) that has a Map with Ingredients as instance variables?
Happy for any suggestions, thanks in advance :)
Please do not initialize all these objects in the Ingredient class itself. That would be a bad practice for oops.
Just think your class is a template from which you create copies(objects) with different values for attributes. In real world if your class represent model for a toy plane which you would use to create multiple toy planes but each bearing different name and color then think how such a system would be designed. You will have a model(class). Then a system(another class) for getting required color and name from different selection of colors and names present(like in database,files,property file ) etc.
Regarding your situation .
If predetermined values store the values in a text file,properties file,database,constants in class etc depending on the sensitivity of the data.
Create Ingredient class with constructors
Create a class which will have methods to initialize Ingredient class using predetermined values,update the values if required,save the values to text file -database etc and in your case return as map .
Also check the links below
http://www.tutorialspoint.com/design_pattern/data_access_object_pattern.htm
http://www.oracle.com/technetwork/java/dataaccessobject-138824.html
Sounds to me like you are looking for a static Map.
public class Ingredient {
private String identifier;
private double ingredientFactor;
private String titleInterface;
public Ingredient(String identifier, double ingredientFactor, String titleInterface) {
this.identifier = identifier;
this.ingredientFactor = ingredientFactor;
this.titleInterface = titleInterface;
}
static Map<String, Ingredient> allIngredients = new HashMap<String, Ingredient>();
static {
// Build my main set.
allIngredients.put("Almonds (ground)", new Ingredient("Almonds (ground)", 0.7185, "Almonds (ground)"));
}
}
There is a question on my mind for a while. Let's say we have the following classes:
public Class Person{
String name;
String address;
String description;
}
public Class PersonFacade{
String name;
String address;
String desc;
}
as you can see the only difference between these two classes are the name of one variable. My question is what is the best way to write a helper class to map the values of one object to another object. Let's assume we have the following:
Person person = new Person();
person.name="name1";
person.address="address1";
person.description="description1";
I want to write a class that is supposed to do the following (let's call it Transformer class)
PersonFacade personFacade = new PersonFacade();
TransformClass.transformFrom(person, personFacade);
What I want this TransformClass.transformFrom() method to do is the follwoing:
based on the similarity of the variable names, assign the value of the variable from "FromClass" to "ToClass"
so in our case, I want it to assign personFacade.name = "name1", personFacade.address="adderss1" and personFacade.desc = "description1" (this last one seems harder to accomplish, but let's try)
Any ideas?
You can use Dozer:
Dozer is a Java Bean to Java Bean mapper that recursively copies data
from one object to another. Typically, these Java Beans will be of
different complex types.
Dozer supports simple property mapping, complex type mapping,
bi-directional mapping, implicit-explicit mapping, as well as
recursive mapping. This includes mapping collection attributes that
also need mapping at the element level.
Look at this: http://dozer.sourceforge.net/
It's a great JavaBean Mapper.
Here the "Getting Started":
http://dozer.sourceforge.net/documentation/gettingstarted.html
Perhaps you can write your own Annotation class in order to create the relationship between the classes. So, for example
public Class Person{
#MyAnnotation(id='name')
String name;
#MyAnnotation(id='addr')
String address;
#MyAnnotation(id='desc')
String description;
}
public Class PersonFacade{
#MyAnnotation(id='name')
String name;
#MyAnnotation(id='addr')
String address;
#MyAnnotation(id='desc')
String desc;
}
Then in your TransformClass, you simply need to iterate through the annotations, find a match and set the corresponding field value with the help of Reflection.