I have a Map Object and the data in map is like
col1 -> data1, col2 -> data2, col3 -> data3 ...
Is it possible to convert this Map to Java Object like
class MapObj {
String col1 = "data1";
String col2 = "data2";
String col3 = "data3";
}
Whilst it is possible to create classes at runtime with custom class loaders, it is relatively pointless. How would you access the fields (other than reflection and other dynamically created classes)?
use Jackson
import com.fasterxml.jackson.databind.ObjectMapper;
public class Foo {
{
ObjectMapper objectMapper = new ObjectMapper();
YourObject obj = objectMapper.convertValue(YourMap, YourObject.class);
}
}
BeanUtils.populate(entry,map);
Are there a fixed set of named entries in the Map? If so, you can just create the MapObj class as you have it and assign the three fields by saying myMapObj.col1 = myMap.get("col1"); and so on.
But stepping back from this question for a moment, what's the larger problem you're trying to solve? A Map itself is actually a very convenient container for this data already, so perhaps you can just use the Map for the same purpose that you were planning to use MapObj for?
I don't see any point in putting a bunch of Map values to a class.
If you want static access, why not try the opposite:
class MapAccess {
Map<String, String> backingMap = ...
public String getCol1() {
return backingMap.get("col1");
}
public String getCol2() {
return backingMap.get("col2");
}
public String getCol3() {
return backingMap.get("col3");
}
}
This way, you'r application doesn't need to know about the Map and you don't get lost with reflection.
I don't know of any pre-made libs that will do it for you, but it should be quite trivial using the java.lang.reflect API. Specifically, the Field#set* methods. Of course, however, you would need to have a pre-defined class with the fields (keys) defined.
Related
can you tell me if exist some pretty way to map one entity object to another dto object? When I needed convert List<ObjEntity> to List<ObjDTO> I created that function:
public class Converter {
public static Function<ObjEntity, ObjDTO> MYOBJ_ENTITY_TO_DTO = objEntity -> {
ObjDTO dto = new ObjDTO();
dto.setId(objEntity.getId());
dto.setName(objEntity.getName());
dto.setNote(objEntity.getNote());
// ...
return dto;
};
}
and I use it like this:
List<ObjDTO> dtos = objEntitiesList.stream().map(Converter.MYOBJ_ENTITY_TO_DTO).collect(Collectors.toList());
But what if I need convert just ONE object? Should I use that function MYOBJ_ENTITY_TO_DTO for that and how? Or what is the best practice? Yes, I can do classical function in Converter class like that:
public static ObjEntity dtoToEntity(ObjDTO dto) {
// map here entity to dto and return entity
}
but it is old style. Exist some new practice in java 8? Something similar like my example for list by lambda?
ObjDTO dto = MYOBJ_ENTITY_TO_DTO.apply(entity);
I see the other way around more often: instead of MYOBJ_ENTITY_TO_DTO, define entityToDto as a method and use
List<ObjDTO> dtos = objEntitiesList.stream().map(Converter::entityToDto).collect(Collectors.toList());
for lists.
I have a web project with 2 Java Entities(Lets Say E1,E2) like how mybatis and VO works.
Object structure:
class E1{
String a;
.... n other data members
E2 e2;
}
class E2{
String b;
.... n other data members
}
Is it possible to make a single class in Android project, i.e.
class E1 {
String a;
String b; //This Data member belongs to class E2
}
and parse it with the help of a framework (like Jackson) or I have to write a custom class for that?
My JSON Data will look like this:
{
"E1": {
"a": "some data",
.
.
.
"E2": {
"b": "some data",
.
.
other data
}
}
}
Is there any API which can do this?
I asked this because with my web Application its not just 2 Class but atleast 10 interconnected class and I am not Using them in my android app. So don't wanna replicate the same classes in android app.
Also if you can suggest any other possible way.
It would be a very bad design practice/approach, making things very difficult to debug, error prone and not future proof (think about it, what if you add to one of the 10 classes a field that conflict with another class' field?).
Anyway, if you still want to trick your way out of the correct approach that would be to have 10 classes, I am not aware of any lib that provides you with this feature. You could parse json ==> 10 Java Map, then merge the 10 Map through the Map::putAll method and finally pass the obtained Map that contains all the objects to Jackson.
Your best bet is to use #JsonAnySetter annotation from Jackson library on the receiver POJO.
public class E1{
public String a;
private Map<String, Object> paramMap = new HashMap<>();
#JsonAnyGetter
public Map<String, Object> getParamMap() {
return paramMap;
}
#JsonAnySetter
public void setParamMap(String s, Object o) {
paramMap.put(s, o);
}
}
This will put every unimplemented attributes in a HashMap.
In combination with #JsonAnyGetter, the serialization of the receiver POJO will give the same result as the JSON input.
I have one ArrayList of PageSummary object and I want to be set value from list object to my Model class attributes using java 8.
public class XXXX {
for(PageSummary ps : pageSummaryList){
model = new Model();
model.setName(ps.getName());
model.setContent(getContent(ps.getName()));
model.setRating(getAverageRating(ps.getName()));
modelList.add(model);
}
private String getContent(String sopName){}
private AverageRatingModel getAverageRating(String sopName){}
}
Here getAverageRating function return integer between 1-5 and getContent return string.
Here are some hints:
create a PageSummary stream from the list
map from PageSummary to Model
collect the Model object
Here are some tutorials:
https://docs.oracle.com/javase/tutorial/collections/streams/reduction.html
https://docs.oracle.com/javase/tutorial/collections/streams/index.html
First, you should create a Model constructor with a PageSummary argument.
public Model(PageSummary ps) {
this.setSopName(ps.getName());
this.setSopContent(getContent(ps.getName(), clientCode, context, httpcliet));
this.setAverageRating(getAverageRating(ps.getName(), clientCode, context, httpclient));
}
Thanks to this, you can shorten the loop:
for (PageSummary ps : pageSummaryList) {
ModelList.add(new Model(ps));
}
And easily use the Stream API:
// This solution is thread-safe only if ModelList is thread-safe
// Be careful when parallelizing :)
pageSummaryList.stream().map(Model::new).forEach(ModelList::add);
or
// A thread-safe solution using Stream::collect()
List<Model> models = pageSummaryList.stream()
.parallel() // optional :)
.map(Model::new)
.collect(Collectors.toList());
ModelList::addAll(models); // I suppose you don't need us to implements this one!
Thanks Alexis C. for pointing out that using the collect approach avoid concurrency issues in case of parallelization :)
I have a model with some properties e.g.
public class Example
{
long id;
String a, b;
int c, d;
boolean e;
}
Now I want to create a method like this
public void update(long id, Map<String, Object> properties)
{
....
}
in this properties map I want to have sth like
properties.put("a","Test");
properties.put("c", 8);
I'm not exactly sure on how to achieve this.
at the end I want to do sth like this:
Example e = new Example(....);
.....
e.update(5L,properties);
can some1 point me to the correct path? I cant figure out a searchterm that doesnt lead me to the Properties or HashMap entries.
thanks in advance
You are searching for the keyword reflection. With reflective access you would write your update method like that:
public void update(long id, Map<String, Object> properties) {
Object obj = getObjectById(id); // you have to implement that method
for (String property : properties.keySet()) {
Field field = obj.getClass().getField(property);
field.set(obj, properties.get(property));
}
}
Note, that I did not declare or handle any exceptions that come along with reflection.
A completely other issue: Why do you want to do it this way? Using reflection to update fields of an object smells like a real design issue. You really should consider another model.
So I have three important factors, filenames which there are many, there will also be duplicates, violation types which there are 6 of, and the data relating to them.
I was thinking of using a Map for this but it only accepts two types, so I want to sort the data by the filename and for every entry under that filename, i want to retrieve the violation type, from what i want it to retrieve all the matches from the data, so say it's a map I could of said map.get(filename, violation) and it will retrieve all the results that match that.
Is there a data structure that can allow me to do this? or am I being lazy and should just sort the data myself when it comes to outputting it.
One other way to approach this would be to use a custom Class for holding the needed data. Essentially 'building' your own node that you can iterate over.
For example! you could create the following class object: (Node.java)
import java.util.*;
public class Node
{
private String violationType;
private String dataInside;
public Node()
{
this("", "");
}
public Node(String violationType)
{
this(violationType, "");
}
public Node(String violationType, String dataInside)
{
this.violationType = violationType;
this.dataInside = dataInside;
}
public void setViolationType(String violationType)
{
this.violationType = violationType;
}
public void setDataInside(String dataInside)
{
this.dataInside = dataInside;
}
public String getViolationType()
{
return violationType;
}
public String getDataInside()
{
return dataInside;
}
}
ok, great, so we have this 'node' thing with some setters, some getters, and some constructors for ease of use. Cool. Now lets see how to use it:
import java.util.*;
public class main{
public static void main(String[] args){
Map<String, Node> customMap = new HashMap<String, Node>();
customMap.put("MyFilename", new Node("Violation 1", "Some Data"));
System.out.println("This is a test of the custom Node: " + customMap.get("MyFilename").getViolationType());
}
}
Now we have a map that relates all of the data you need it to. Now, you'll get a lot of people saying 'Don't reinvent the wheel" when it comes to things like this, because built in libraries are far more optimized. That is true! If you can find a data structure that is built into java that suits your needs, USE IT. That's always a good policy to follow. That being said, if you have a pretty custom situation, sometimes it calls for a custom approach. Don't be afraid to make your own objects like this, it's easy to do in Java, and it could save you a lot of time and headache!
EDIT
So, after re-reading the OP's question, I realize you want an entire list of associated data for the given violation of a given filename. In which case, you would switch the private String dataInside to something like private ArrayList<String> dataInside; which would allow you to associate as much data as you wanted, still inside that node, just inside of an arraylist. Also note, you'd have to switch up the getters/setters a little to accomodate a list, but that's not too bad.
You could use a custom class for a mapkey which contains the two fields filename and violation type. When doing so you need to implement equals() and hashCode() methods do ensure instances of that class can be used as key for map.
You can use TreeMap. TreeMap is sorted according to the natural ordering of its keys.
TreeMap<String, List<String>> map = new TreeMap<String, List<String>>();