I'm trying to learn streaming syntax and I'm struggling to convert some for loops into a stream. If this is inappropriate here let me know and I'll delete.
Essentially I have a list of pojo's (with nested pojos) which I'm using to create a new list of different pojo's
(entity to model).
The (working) for loop is like this
for (Pojo1 p1 : pojo1.getPojo1List())
{
List <String> stringList = new ArrayList<>();
for (Pojo2 p2 : p1.GetPojo2List())
{
stringList.add(p2.getText());
}
Pojo3 p3 = new Pojo3(p1.getMember1(), p1.getMember2(), stringList);
}
I have replace the inner loop with a stream pipeline giving
for (Pojo1 p1 : pojo1.getPojo1List())
{
List <String> stringList = p1.GetPojo2List().stream().map(Pojo2::getText).collect(Collectors.toList());
Pojo3 p3 = new Pojo3(p1.getMember1(), p1.getMember2(), stringList);
}
This is working properly.
I would now like to replace the first loop though and I'm struggling to work out which way to go to do this. I started with something like this
pojo1.getPojo1List().stream().forEach(p1 -> new Pojo3(p1.getMember1(), p1.getMember2(), [stream from above])
This is not working but before I play with it too much it occurred to me that as foreach is a terminal operator this approach is probably wrong as I wouldn't be able to collect the pojos I create (?)
Can anyone point me in the right direction ?
Related
hope you are doing well.
I have some list of other object which again contains two different objects. I have tried couple of ways using Collectors.groupingBy() but didn't get expected output. So help me to figure out solution to this.
Suppose I following three entities:
class FruitFlower {
Fruit fruit;
Flower flower;
}
class Fruit {
String name;
}
class Flower {
String name;
}
And I have a list like this
List<FruitFlower> fruitFlowers = new ArrayList<>();
fruitFlowers.addAll(
new FruitFlower(
new Fruit("Apple"),
new Flower("Rose")
),
new FruitFlower(
new Fruit("Banana"),
new Flower("Lily")
),
new FruitFlower(
new Fruit("Apple"),
new Flower("Sunflower")
),
new FruitFlower(
new Fruit("Banana"),
new Flower("Purple")
),
new FruitFlower(
new Fruit("Banana"),
new Flower("Rose")
)
);
Now, I want to order this list by some filter such that it returns HashMap like this
HashMap<Fruit,List<Flower>> hashMap=new HashMap<>();
Resultant Object:
{
"Apple":["Rose","Sunflower"]
"Banana":["Lily","Purple","Rose"]
}
Where
Expected output is a HadhMap that contains only unique values and a list of other values connected to that particular object. You can consider Objects of String for simplicity.
This is Java question and expected answer should be in Java 8 using stream API.
Thank you in advance.
As you suspected, groupingBy is the right approach.
fruitFlowers.stream().collect(Collectors.groupingBy(
i -> i.fruit,
Collectors.mapping(i -> i.flower, Collectors.toList())
));
The first parameter to groupingBy defines how you want to group them. In this case, we want to group by fruits.
The second parameter describes what the value of the resulting map should be. In this case, we want the values to be the list of flowers.
Note that this approach only works if groupingBy can deduce that two fruits are equivalent. This requires that the Fruit class contains an appropriate implementation of equals and hashCode.
If the Fruit class cannot be extended to add those methods, one can change the first lambda to i -> i.fruit.name, but that would make the resulting Map to have String keys instead of Fruit.
Good Morning.
I'm starting to learn some mongo right now.
I'm facing this problem right now, and i'm start to think if this is the best approach to resolve this "task", or if is bettert to turn around and write another way to solve this "problem".
My goal is to iterate a simple map of values (key) and vector\array (values)
My test map will be recived by a rest layer.
{
"1":["1","2","3"]
}
now after some logic, i need to use the Dao in order to look into db.
The Key will be "realm", the value inside vector are "castle".
Every Realm have some castle and every castle have some "rules".
I need to find every rules for each avaible combination of realm-castle.
AccessLevel is a pojo labeled by #Document annotation and it will have various params, such as castle and realm (both simple int)
So the idea will be to iterate a map and write a long query for every combination of key-value.
public AccessLevel searchAccessLevel(Map<String,Integer[]> request){
Query q = new Query();
Criteria c = new Criteria();
request.forEach((k,v)-> {
for (int i: Arrays.asList(v)
) {
q.addCriteria(c.andOperator(
Criteria.where("realm").is(k),
Criteria.where("castle").is(v))
);
}
});
List<AccessLevel> response=db.find(q,AccessLevel.class);
for (AccessLevel x: response
) {
System.out.println(x.toString());
}
As you can see i'm facing an error concerning $and.
Due to limitations of the org.bson.Document, you can't add a second '$and' expression specified as [...]
it seems mongo can't handle various $and, something i'm pretty used to abuse over sql
select * from a where id =1 and id=2 and id=3 and id=4
(not the best, sincei can use IN(), but sql allow me)
So, the point is: mongo can actualy work in this way and i need to dig more into the problem, or i need to do another approach, like using criterion.in(), and make N interrogation via mongotemplate one for every key in my Map?
Lets say I have a list of rooms
List<Room> rooms;
And each room has a list of persons.
Using java8 streams I want to iterate the list of rooms, get all persons, execute some method on each node (doSomething()) and get a list of all the filtered objects.
Is this the best practive using java 8?
List<Asset> pesonsList= new ArrayList<>();
for (Room room : rooms)
room.getPersonsList().stream()
.filter(person -> person.isTall())
.forEach(person -> {
doSomething(person);
pesonsList.add(person);
});
You'd probably better do it like this:
List<Person> persons =
rooms.stream()
.flatMap(room -> room.getPersonsList().stream())
.filter(Person::isTall)
.peek(this::doSomething)
.collect(Collectors.toList());
In addition to the #JBNizet answer I'd suggest to replace getPersonsList() in Room class with persons() method: instead of
List<Person> getPersonsList() {...}
Create this method:
Stream<Person> persons() {...}
The first advantage is that streaming operations will become shorter:
List<Person> persons = rooms.stream()
.flatMap(Room::persons)
.filter(Person::isTall)
.peek(this::doSomething)
.collect(Collectors.toList());
The second advantage is that it might be more implementation independent, thus more efficient. Suppose that internally you store persons in the Set or in array. When having getPersonsList() method you will need to copy all the persons to the new list first. When having persons() method, you can easily create a stream directly from your internal data structure whatever it is. I believe, it's Java 8 way to return the stream of internal objects instead of some specific data structure were it List or array or whatever.
Using Apache Cayenne I am trying to figure out how to avoid doing iterative calls to the DB when I have a Collection of attribute values.
Say we have a persistent object Person with an attribute name of type String. If I have a List containing names of the Person I would like to generate an expression that allows a single DB call rather than iterating over the list and getting each Person in turn.
This doesn't actually exist but I would like something like this:
List<String> names = ...;
ExpressionFactory.orLikeExp(Person.NAME_PROPERTY, names);
You can use ExpressionFactory.join(..):
List<Expression> pairs = new ArrayList<>(names.size());
for(String name : names) {
// use an expression appropriate for comparison...
// "like" in this example, but can be "equals", etc.
pairs.add(ExpressionFactory.likeExp(Person.NAME_PROPERTY, name));
}
Expression e = ExpressionFactory.joinExp(Expression.OR, pairs);
I'm trying to create a new Dictionary and inject it in the IORegistry. I've managed to inject simple strings or data values but thats it.
My approach is via a modified IOPCIFamily.kext, and it's not for a specific purpose but just for learning.
My code for 1 line values is something like this
if (product == id){ setProperty("test", "test") }
and another approach
if (product == id){ propTable->setObject("TEST", prop) prop->release(); }
propTable is the Parent Dictionary, so i must create a child Dictionary to which i can inject values with setObject parameter.
Does anyone have an idea on how to do this? I suspect it must be something like this:
propTable->newTable->setObject(etc)
but i didn't figure how to create the newTable for propTable to insert it in the existing one of what ever product == ids it finds.
Thank you very much, sorry if it's confusing. Not used to explain code related stuff in english.
If I understand your question correctly, you want the OSDictionary::withCapacity factory function.
For example:
OSDictionary* prop_dict = OSDictionary::withCapacity(1);
OSString* val = OSString::withCString("test");
if (!prop_dict || !val)
{
// handle error...
}
prop_dict->setObject("test", val);
val->release(); val = NULL;
and then, to use it in you property table:
propTable->setObject("NewProperty", prop_dict);
prop_dict->release(); prop_dict = NULL;