Java work with class as collection to add items - java

This class below is my simple code which it is deployed ModelMarkets and I want to add item to this class List but I can't. Please help me to implement that.
My base class:
public class ModelMarkets extends RealmObject implements Parcelable {
#PrimaryKey
private String id;
private String marketId;
private String marketTitle;
...
}
And create a list from that and add an item to that class:
public class ModelMarketLists {
private List<ModelMarkets> modelMarkets = new ArrayList<>();
public ModelMarketLists(List<ModelMarkets> modelMarkets) {
this.modelMarkets = modelMarkets;
}
public ModelMarketLists(JSONArray lists) {
}
public void add(ModelMarketLists t){
/* modelMarkets.addAll(t); */
}
}
How can I add class collection data to modelMarkets as List ?

The type ModelMarketLists has a method public void add(ModelMarketLists t) but you are trying to invoke add(ModelMarkets), which will only work if ModelMarkets is a subtype of ModelMarketLists or if ModelMarketLists contains an overload like public void add(ModelMarkets modelMarkets).
Also, you should follow the Java naming conventions. Local variable names should start with a lower-case letter, be spelled in camel case, be long enough to be meaningful, reflect correct natural-language spelling, and reflect the semantics of the variable in the problem domain.

Related

Implementing a generic container for a list of interface instances in Java

Java 8 here. I have the following POJOs:
public interface HasPartNumber {
String getPartNumber();
}
#Getter
#Setter
public class InventoryItem implements HasPartNumber {
private String modelNumber;
private String description;
// lots of other fields here
#Override
public String getPartNumber() {
return this.modelNumber;
}
}
public class Inventory extends ArrayList<InventoryItem> {
// Inventory is just an alias of a list of InventoryItem
}
#Getter
#Setter
public class PriceItem implements HasPartNumber {
private String equipmentNumber;
// lots of other fields here
#Override
public String getPartNumber() {
return this.equipmentNumber;
}
}
public class PriceRoster extends ArrayList<PriceItem> {
// PriceRoster is just an alias of a list of PriceItem
}
I understand some of you may have an aversion to how I'm modeling Inventory and PriceRoster, but using the is-a and has-a golden rule, it is correct. An "inventory" is no more and no less than just a list of InventoryItems. Ditto for PriceRoster. And, the Domain-Driven Design community would probably agree that these are valid data models if it makes sense to a developer reading the code.
However, I am not married to this design. And so while my druthers would be to keep this data model above, if it truly is impossible to accomplish what I describe below without changing the data model, I'll be flexible.
I am trying to write a generic PartProcessor class that will iterate through lists of HasPartNumber impls and perform processing on them. My best attempt:
public class PartProcessor<PART_CONTAINER extends List<HasPartNumber>> {
public void process(PART_CONTAINER partContainer) {
partContainer.stream().forEach(part -> {
// Do something here
});
}
}
produces compilation errors when I go to instantiate the PartProcessor:
PartProcessor<Inventory> inventory = new PartProcessor<Inventory>();
The compiler errors I'm seeing are:
"Type parameter 'com.example.myapp.Inventory' is not within its bound; should implement 'java.util.List<com.example.myapp.HasPartNumber>'"
Any ideas what I can do to get my PartProcessor working generically on any list of HasPartNumbers impl, including Inventory and PriceRoster?
bounded types makes the type covariant:
public class PartProcessor<PART_CONTAINER extends List<? extends HasPartNumber>> {...
For a broader read see this answer also.

How can I 'group' custom classes together?

I have some custom classes, which contain information about different viewtypes in a RecyclerView, like title, description, etc (there are different variables for each class though). I want to add these classes to an ArrayList, but I don't want it to be a generic (Object?) ArrayList, I want to make sure only my custom classes can be put in. Now I could do this by making another class for it with a setter and getter, and do some checks, but I'd rather have something like ArrayList<CustomGroup>, where CustomGroup could be any of CustomClass1, CustomClass2, etc... Is this possible, and if so, how would I do this?
Example:
public class CustomClass1 {
String title, description;
int amount;
// Getter & Setter
}
public class CustomClass2 {
String errorMessage;
int errorCode;
// Getter & Setter
}
public class CustomClass3 {
String warningName;
double amount;
// Getter & Setter
}
ArrayList<CustomGroup> arrayList = new ArrayList<>();
CustomClass3 customClass3 = new CustomClass3();
// Set values for customClass3
arrayList.add(customClass3);
CustomClass1 customClass1 = new CustomClass1();
// Set values for customClass1
arrayList.add(customClass1);
I would recommend using an interface for this. You can use interfaces as "tags", where the interface basically defines nothing but the classes you want to allow in the list implement it. In your case, however, you could have the interface define the String and int properties.
Interface "tag" with nothing specified
public interface ICustomClassInterface {
}
public class CustomClass1 implements ICustomClassInterface {
String title, description;
int amount;
}
ArrayList<ICustomClassInterface> arrayList = new ArrayList<ICustomClassInterface>();
Only classes that implement the interface can be added to the list. However, your issue here is you will be getting to them through this interface which defines nothing, i.e. you will need to figure out what type it is.
Ideally you would refactor your classes to have the common functionality either defined in an abstract class or specified in an interface, then you don't need to care what the actual type is.
Interface with needed properties defined
public interface ICustomClassInterface {
String FieldA;
int FieldB;
}
public CustomClass1 implements ICustomClassInterface {
String FieldA;
int FieldB;
}
ArrayList<ICustomClassInterface> arrayList = new ArrayList<ICustomClassInterface>();
I would agree with the other answer which suggests using an interface. I would add that, since the examples that you show do not have the same types, you'll find yourself doing checks; perhaps like:
if (someClass instanceof CustomClass1) {
...
} else if (someClass instanceof CustomClass2) {
...
} else if (someClass instanceof CustomClassN) {
...
} else { ... }
That's not very extensible or easily maintained.
You could use the interface, whether empty or with common attributes of the same type, but it might get ugly though doing said checks. Maybe what you could do to avoid that is add a CustomClassProcessor class which will have overloaded methods for the various types you have to handle; this is called the visitor pattern.
public class CustomClassProcessor {
public void process(CustomClass1 cc) {
// Do stuff for CustomClass1
}
public void process(CustomClass2 cc) {
// Do stuff for CustomClass2
}
public void process(CustomClass cc) {
// Do stuff for CustomClass3
}
...
}
Your interface would be like so:
public interface CustomClass {
public void getProcessed(CustomClassProcessor cp);
}
One example of a concrete custom class would be:
public class CustomClass1 implements CustomClass {
#Override
public void getProcessed(CustomClassProcessor cp) {
cp.process(this);
}
}
And you'd use it like:
for (CustomClass cc : list)
cc.getProcessed(customClassProcessor);
or with Java 8 features...
list.forEach(cc -> cc.getProcessed(customClassProcessor);
You have several absolutely different objects and requirement to join it with array list to show it in recyclerView by position. So you have to use ArrayList of Object's(or another collection of objects) and you can't avoid it and pospone checking types.
You have to create such list and make connection of concrete class of stored object with item type (in getItemType) via using instanceof. After that you can create viewHolders according to these types and then in onBindViewHolder cast current item to connected viewHolder or encapsulate casting in concrete view holders

How to define a field to have multiple types?

I have a class that I wish to take two different types of inputs (via one constructor argument) and process polymorphically. Everything in the class is the same except for the handling of these two different input types, and I don't wish to duplicate all the code just due to the need for one field to have variable type. I guess my question is how to define a field to have a variable type? Or is this just bad practice? See my simple example below where I use *Map or Set* as a placeholder representing the variable type I wish to use for a field or method return type.
public abstract class ReturnTwoTypes {
public abstract Map<String,Double> *or* Set<String> runProgram();
}
private class ReturnSetType extends ReturnTwoTypes{
#Override
public Set<String> runProgram(){
return new TreeSet<String>();
}
}
private class ReturnMapType extends ReturnTwoTypes{
#Override
public Map<String, Double> runProgram(){
return new TreeMap<String, Double>();
}
}
private class UsesReturnTwoTypes{
//This class has a bunch of code I wish to reuse by not defining separate classes for both the Map and Set version of the MapOrSet field
private ReturnTwoTypes twotypes;
private Map<String,Double> *or* Set<String> mapOrSet;
public UsesReturnTwoType( ReturnTwoTypes twotypes ){
this.twotypes = twotypes;
}
public void runProgram(){
mapOrSet = twotypes.runProgram();
}
}
Make your class generic:
public abstract class ReturnTwoTypes<T> {
public abstract T runProgram();
}
private class ReturnSetType extends ReturnTwoTypes<Set<String>> {
#Override
public Set<String> runProgram(){
return new TreeSet<String>();
}
}
An attribute can not have multiple types, using a generic Object as suggested in comments and answer is really dirty. You could either use generic methods or have your method return a custom object.
You could declare them as Object and store whatever reference you want. Then you can use instanceof or getClass().getName() to check what is in there and take action appropriately.

Making a comparator for two classes that extend super

My apologies for my limited knowledge of generics beforehand.
I have the following situation:
Class 1:
public class PostProcess implements Serializable {
public int order;
// Several other variables.
// Constructor setting vars
public PostProcess(){
}
/* Getters and setters for variables */
}
Class 2:
public class Application extends PostProcess{
public int subOrder;
// Several other variables.
// Constructor setting vars
public Application(){
}
/* Getters and setters for variables */
}
Class 3:
public class FileOperation extends PostProcess{
public int subOrder;
// Several other variables (different from class 'Application').
// Constructor setting vars
public FileOperation(){
}
/* Getters and setters for variables */
}
What I am trying to achieve in a different class is to sort a list containing a mix of 'FileOperation' and 'Application' objects defined as:
private ArrayList<? extends PostProcess> processList = new ArrayList<PostProcess>();
This sort will have to be on two fields of both of these objects, namely: 'order' and 'subOrder'. 'order' is inherited from PostProcess and 'subOrder' is defined in both the 'Application' and 'FileOperation' classes.
Throughout my journey of reading up on Generics, Comparable, Comparators and Interfaces I think I got things mixed up.
I am trying to apply a sort using:
Collections.sort(processList, new PostProcessComparator());
The PostProcessComparator is defined as:
public class PostProcessComparator implements Comparator<? extends PostProcess> {
#Override
public int compare(Object p1, Object p2) {
int mainOrderCompare = p1.getOrder().compareTo(p2.getOrder());
if (mainOrderCompare != 0) {
return mainOrderCompare;
} else {
return p1.getSubOrder().compareTo(p2.getSubOrder());
}
}
}
Questions:
I know my Comparator (and possibly more) is wrong, but I dont know where specifically. Im here to learn ;)
I noticed that defining the 'processList' List isnt the right way to do it. When I try to add an 'FileOperation' or 'Application' object to the List the compiler slaps me in the face with "no suitable method found for add(Application)" (the same for FileOperation). Did I incorrectly assume that I could use generics to declare my processList types? should be correct as both classes have PostProcess as their superclass right?
Defining the PostProcessComparator with class bounds should work in my eyes as I only want to be able to compare objects that have PostProcess as a superclass (and thus have access to the same methods).
How do I access the argumented objects in the Comparator class for p1 and p2 (because I still need to declare their types for the arguments:
#Override
public int compare(<What to put here?> p1, <And here?> p2) {
}
I really hope you guys can help!
If I was unclear in something, do let me know and ill elaborate.
Thanks!
EDIT
Thanks to NickJ and Winzu I have made the necessary changes to the comparator and the ArrayList definition.
I have moved subOrder from Application and FileOperation to the parent class (and made them protected)
Redefined parameterization of the comparator to:
public class PostProcessComparator<T extends PostProcess> implements Comparator<T>
Made use of the Integer.compare(p1.getOrder(), p2.getOrder()) for initial comparator comparisons.
Now the final challenge (compiler warnings)
Upon calling:
Collections.sort(processList, new PostProcessComparator());
I get the warning:
- [unchecked] unchecked method invocation: method sort in class Collections is applied to given types
required: List<T>,Comparator<? super T>
found: ArrayList<PostProcess>,PostProcessComparator
The parameterization is correct for this comparator in my eyes, aside from the fact that i havent checked the object types.
Where does this go wrong?
The only problem I found was that you need to parameterise PostProcessComparator like this:
public class PostProcessComparator<T extends PostProcess> implements Comparator<T> {
#Override
public int compare(T p1, T p2) {
int mainOrderCompare = p1.getOrder().compareTo(p2.getOrder());
if (mainOrderCompare != 0) {
return mainOrderCompare;
} else {
return p1.getSubOrder().compareTo(p2.getSubOrder());
}
}
}
Now the compare() method will accept the correct class (extends PostProcess) and so any public methods of PostProcess may be called from within comlpare()
Finally, your fields should not be public. I suggest making the fields protected, so subclasses may still inherit them, but encapsulation is maintained.
NickJ's answer above shows how to implement the comparator.
For what you're doing you also want to change
private ArrayList<? extends PostProcess> processList = new ArrayList<PostProcess>();.
to
ArrayList<PostProcess> processList = new ArrayList<PostProcess>();
This is why you can't add your Application et FileOperation objects into your list.
It's a bit tricky. Maybe this post can help you understand
Java using generics with lists and interfaces
You also want SubOrder in the parent class.
import java.io.Serializable;
public class PostProcess implements Serializable {
private int order;
private int subOrder;
// Several other variables.
public int getSubOrder() {
return subOrder;
}
public void setSubOrder(int subOrder) {
this.subOrder = subOrder;
}
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
// Constructor setting vars
public PostProcess(){
}
}
Finally call the comparator like this to avoid unchcked warning:
Collections.sort(processList, new PostProcessComparator<PostProcess>());
Just change it to:
public class PostProcessComparator implements Comparator<PostProcess> {
#Override
public int compare(PostProcess p1, PostProcess p2) {
//...
}
}
That's it. You have a comparator that can compare any two instances of PostProcess (and instances of subclasses of PostProcess are instances of PostProcess).

How can you pass a List<objects that implement an interface> to a method?

I have a servlet with several methods that get a list of objects from the DAO, turn the list into JSON, and send it back in the response. Every list is made of objects that have a method:
public String getAsJson(){...}
And the servlet has a bunch of mostly identical methods that look like:
private String getUserListAsJson() {
List<User> userList = this.dao.getUsers();
StringBuilder builder = new StringBuilder();
builder.append('[');
// loops over the list appending the value of each objects getAsJson()
builder.append(']');
return builder.toString();
}
The problem is that I have about 6 methods (and growing) that look exactly like that except for different DAO queries. My idea was to create an interface that only had the definition for the getAsJson() method, make each bean implement that, and then have another method in the servlet that took objects that implemented that interface. Ended up looking like this:
public Interface JsonEnabled {
public String getAsJson();
}
public class User implements JsonEnabled {
....
#Override
public String getAsJson() {...}
}
public class TheServlet {
...
private String getUserListAsJson() {
List<User> userList = this.dao.getUsers();
return this.getListAsJson(userList);
}
private String getListAsJson(List<? implements JsonEnabled> list) {
// The loop code that is in each method.
}
}
That doesn't compile though. After looking up some documentation from Oracle, you can only have extends and not implements for generic parameters. Making all the classes extend from an Abstract Class that just has the getAsJson() method doesn't make sense semantically (the classes are unrelated).
I haven't found a good solution on SO or just googling around, so any help/insight would be appreciated.
For generic wildcards the keyword extends works for both classes and interfaces:
private String getListAsJson(List<? extends JsonEnabled> list) { ... }
extends has slightly different meaning when used for defining generic bounds - it essentially translates to "is, or extends, or implements".
Why don't just use
private String getListAsJson(List<JsonEnabled> list) { ... }
?

Categories