Java: Replace a certain parameter of a POJO without iteration - java

I have some list of objects:
List<Object> objectList = new ArrayList<>();
Object.class looks like this:
public class Object {
private String name;
private String age;
... getters & setters ...
}
I want to assign / replace all 'name' parameters inside my objectList to one value, f.e.: "Andrew".
Normally I would do it through iteration, but is there a way to do it without iterating? I have tried collections.replaceAll but failed:
Collections.replaceAll(objectList, object, new Object.setName("Andrew"));

objectList = objectList.forEach(object -> object.setName("Andrew"));

Setting the name field to static you can achieve this only. otherwise you must have to iterate over it.

Related

Streaming over a Java list to populating a Map

Java 11 here. I have the following POJO:
#Data // Lombok; adds getters, setters, all-args constructor and equals and hashCode
public class Fliflam {
private String merf;
private String tarf;
private Boolean isFlerf;
}
I have a method that validates a Flimflam and returns a List<String> of any errors encountered while validating the Flimflam. I can change this to return Optional<List<String>> if anyone thinks thats helpful for some reason, especially when dealing with the Stream API:
public List<String> validateFlimflam(Flimflam flimflam) {
List<String> errors = new ArrayList<>();
// ... validation code omitted for brevity
// 'errors' list is populated with any errors; otherwise it returns empty
return errors;
}
I want to stream (Stream API) through a List<Flimflam> and populate a Map<Flimflam,List<String>> errors map, where the key of the map is a Flimflam that failed validation, and its corresponding value is the list of validation error strings.
I can achieve this the "old fashioned" way like so:
List<Flimflam> flimflams = getSomehow();
Map<Flimflam,List<String>> errorsMap = new HashMap<>();
for (Flimflam ff : flimflams) {
List<String> errors = validateFlimflam(ff);
if (!errors.isEmpty() {
errorsMap.put(ff, errors);
}
}
How can I accomplish this via the Stream API?
Like this
Map<Flimflam,List<String>> errorsMap = flimflams.stream().collect(Collectors.toMap(f -> f, f-> f::validateFlimflam));
toMap takes 2 parameters (keyMapper,valueMapper)
In your case key mapper is object from stream itself, and value is calling validateFlimflam on that object
It is hard to tell where exactly your validateFlimflam method is defined. I suspect it is not in the Flimflam class itself since there would be no need to pass an instance of itself to the method. So I presume it is an external method to that class. Assuming that I would proceed as follows:
thisClass = instance containing validateFlimflam. Could be set to this
Map<Flimflam, List<String>> errorsMap =
flimflams.stream().collect(Collectors.toMap(f -> f,
thisClass::validateFlimflam));
If by chance, Flimflam does contain validateFlimflam you could do it like this. Note that this presumes the method takes no arguments as they wouldn't be necessary
Map<Flimflam, List<String>> errorsMap =
flimflams.stream().collect(Collectors.toMap(f -> f,
Flimflam::validateFlimflam));
Finally, if the containing class is some other class and the validateFlimflam method is declared static, then you could do it like this by using the containing class name, not instance. Also, in this case, the method would take an argument as defined.
Map<Flimflam, List<String>> errorsMap =
flimflams.stream().collect(Collectors.toMap(f -> f,
SomeClass::validateFlimflam));

Create list of an element of an Object from another list of Objects

The model:
public class MyModel{
private int id;
private String name;
....
....
//getters and setters
}
I have a list of MyModel object:
//First Object to be added to list
MyModel myModelObject1 = new MyModel();
myModelObject1.setId(1);
myModelObject1.setName("abc");
//Second Object to be added to list
MyModel myModelObject2 = new MyModel();
myModelObject1.setId(2);
myModelObject1.setName("pqr");
List<MyModel> myModelList = new ArrayList<MyModel>();
myModelList.add(myModelObject1);
myModelList.add(myModelObject2);
I want to get a list of names present in the MyModel List i.e. I want to create a list of names (List<String> in this case) from myModelList. So, I want my list to have:
{"abc", "pqr"}
There is always a way to iterate and create another list but is there any better way to do that? (Not necessarily to be efficient but if it can be done in a line using streams, foreach e.t.c.).
EDIT:
The answers worked for me but I have some modifications in my use case: If I want to add a condition that only name which contains character 'a' should be added to the list and I want to add a logger message to debug for each element then how should I approach this?
I tried doing the following using a method (charAPresent()) which checks that if the passed String contains character 'a' but it didn't work:
List<String> modelNameList = myModelList.stream()
.map(model -> {
if (charAPresent(model.getName)) {
model.getName()
}
})
.collect(Collectors.toList());
Let me know if I am missing something.
Using Java 8 Stream:
List<String> modelNameList = myModelList.stream()
.map(Model::getName)
.collect(Collectors.toList());
Model::getName is called as method reference. It equivalents to model -> model.getName()
You can use streams and map your object to its name and collect to a list as:
List<String> names = myModelList.stream()
.map(MyModel::getName)
.collect(Collectors.toList());
There is always a way to iterate and create another list but is there
any better way to do that
Even with the use of streams, you would have to iterate the complete collection. There is no better way of doing it than iterating the complete collection.
You can use Stream.map() to get only the names of your model. Use Stream.filter() to get only the names matching your charAPresent() method. To log the entries before collecting you can use Stream.peek():
List<String> modelNameList = myModelList.stream()
.map(Model::getName) // map only the name
.filter(YourClass::charAPresent) // filter the items
.peek(System.out::println) // print all items which are in the filter
.collect(Collectors.toList());
You can also use foreach like this:
public static List<String> modelNames(List<MyModel> myModelList)
List<String> list = new ArrayList<String>();
for(MyModel mm : myModelList) {
if(mm.getName().contains("a") {
list.add(mm.getName());
}
}
return list;
}

Collect List into a Map<Object1 , Map<Object2, Object3>> in Java 8

I want to iterate a list of objects. Each of object contains some variables of objects. More specifically:
public class KCenterDocumentMapping {
private DigitalFileCategory digitalFileCategory;
private DocumentType documentType;
private KCenterCategory kCenterCategory;
private KCenterFolder kCenterFolder;
private KCenterDocumentType kCenterDocumentType;
//setters & getters
}
My list is:
List<KCenterDocumentMapping> allMappings = db4.retrieveMapping();
The desired Map Structure is:
Map<DigitalFileCategory, Map<DocumentType, KCenterDocumentMapping>> kCenterDocumentMappingMap = new HashMap<>();
In my current implementation I received "non-static method cannot be referenced from a static context".
Map<DigitalFileCategory, Map<DocumentType,KCenterDocumentMapping>> grouping = kCenterDocumentMappingList.stream()
.collect(Collectors.groupingBy(KCenterDocumentMapping::getDigitalFileCategory,
Collectors.mapping(KCenterDocumentMapping::getDocumentType, this)));
Any ideas?
Collectors.mapping(KCenterDocumentMapping::getDocumentType, this) // this?
I think you are looking for is :
Collectors.toMap(KCenterDocumentMapping::getDocumentType,
Function.identity())
Collectors.mapping accepts a Function and a Collector as input; this does not look like a Collector

Can a list have more than one lists in java?

i am trying to retrieve records from the db for three different columns. I need a way to store the data from these columns so that i am able to iterate through the first column and put some checks on the data from the other two columns. the first thing i was trying was to have three different list and each list having records from those three columns simultaneously but that way i wont be able to return all the three lists from a single method, I need all those data retrieved from the db and then i am gona use it in another class. Is there a way a list can have more than one lists inside of it. Is there any other solution for this problem, an other suggestions.
thanks.
Create a bean (Say DbResult) with three fields column1, column2 and column3.
Then create and return a list of DbResult: List<DbResult> resultList = new ArrayList<DbResult>();
This way you can pass all your data to the caller method;
Review DTO patern DTO
In java you would declare a class with three fields. For example like this:
public class Person {
public String firstName;
public String lastName;
public String birthName;
}
(if you prefer, you can also use getter and setter methods)
You can then store instances of that class in a list:
List<Person> persons = new ArrayList<>();
Person person = new Person()
person.firstName = "Mario"
...
persons.add(person);
If you are not allowed to create new Java-files (for whatever reason...), than you can even include the Person class inside of another class or interface:
public class ExistingClass {
public static class Person {
...
}
...the rest of the the existing class...
}
You should create a class which ll hold a row's data from the tabel.
Like :
Class Row {
int column1;
int column2;
int column3;
}
And then you should create a list of this class objects like : List<Row>.
In this way you can iterate through one list and access all column values and you can also return the list in any function.

Java array with multiple values

I want to create a multidimensional array where each of the nodes will have the following details:
Place Name ex: "Mysore" , "Bangalore"
Icon name ex: "waterfall", "wildlife"
Place Distance ex: "200", "123"
Which is the best way to do this when I have over 30 values ?
Example:
"Bangalore", "200", "city"
"Mysore", "100", "historic"
I am trying to populate a list array in Android where each row has three details - name, icon, distance so I want to temp populate that data in my java class.
Don't use a multidimensional array. Use a simple array (or List) of objects:
public class Place {
private String name;
private String icon;
private int distance;
// constructor, methods skipped for brevity
}
...
private Place[] places = new Place[10];
// or
private List<Place> places = new ArrayList<Place>();
Java is an OO language. Learn to define and use objects.
I think best option is create custom defined object.
Class TestObject
{
String Place,Icon,Distance;
// Setter and Getter method
}
// Create object of class. Store your value using setter and getter method
and save object into list
List<TestObject> test = new ArrayList<TestObject>();
test.add(testObject); //
Create a class with the attributes that you want in an element.
now you can create an array of objects of this class.
class Place {
private String name;
private String icon;
private int distance;
public Place(String name,String icon,int distance){
this.name=name;
this.icon=icon;
this.distance=distance;
}
}
Place places[]=new Place[10];
places[0]=new Place("Mysore","wildlife",123);
and so on
beware of instantiating the objects else you will endup getting NullPointerException
If you don't want to create a separate class . You can also use JSON for your purpose.
JSON object is light weight and can manage aaray data very easily.
Like :
JSONObject jo = new JSONObject();
JSONArray ja = new JSONArray();
ja.put("Mysore");
ja.put("wildlife");
ja.put(123);
jo.add(KEY, ja); // Adding array to JSON Object with key [KEY can be any unique value]
JSON are easy to read and manageable.
It provides lots of functionality rather than array.

Categories