How to create a difference between two nested lists - java

I want to create a difference between two lists and their child items.
For the parent objects this is not a problem. But for the child lists I don't know how to get to the solution.
List/Object Structure:
Set<ParentObject>
|
|-Set<ChildObjects>
// example lists with diff
old list
|-MG1
| |-PL1
| |-PL2
|
|-MG2
|-PL1
|-PL2
|-PL3
new list
|-MG1
| |-PL1
| |-PL2
| |-PL3 <- new
|
|-MG2
| |-PL1
| |-PL2
| |-PL3
|
|-MG3 <- new
|-PL1
diff list
|-MG1
| |-PL3
|
|-MG3
|-PL1
Here is the diff between the two Parent lists.
// new minus old = diff
List<ParentObject> diff = newA.stream()
.filter(item -> !oldA.contains(item))
.collect(Collectors.toList());
works pretty well. but the code does not care about the child objects, which can also be different.

Related

Stream Filter List based on Combination of values from another List

Need: To filter out data in list - 1 based on the values present in list - 2 with multiple criteria i.e. combination of Date & Order Number
Issue: Able to filter based on 1 criteria. But when I try adding another filter condition it treats it as 2 separate & not as combination. Unable to figure out how to make it as a combination.
Hope issue faced is clear.
Research: I referred to my earlier query on similar need - Link1 . Also checked - Link2
List 1: (All Orders)
[Date | OrderNumber | Time | Company | Rate ]
[2014-10-01 | 12345 | 10:00:01 | CompA | 1000]
[2015-03-01 | 23456 | 08:00:01 | CompA | 2200]
[2016-08-01 | 34567 | 09:00:01 | CompA | 3300]
[2017-09-01 | 12345 | 11:00:01 | CompA | 4400]
[2017-09-01 | 98765 | 12:00:01 | CompA | 7400]
List 2: (Completed Orders)
[Date | OrderNumber | Time]
[2014-10-01 | 12345 | 10:00:01]
[2015-03-01 | 23456 | 08:00:01]
[2016-08-01 | 34567 | 09:00:01]
[2017-09-01 | 98765 | 12:00:01]
Expected O/p after filter :
[Date | OrderNumber | Time | Company | Rate]
[2017-09-01 | 12345 | 11:00:01 | CompA | 4400]
Code:
// Data extracted from MySQL database
// List 1: All Orders
List<ModelAllOrders> listOrders = getDataFromDatabase.getTable1();
// List 2: Completed Orders
List<ModelCompletedOrders> listCompletedOrders = getDataFromDatabase.getTable2();
// Filter with 1 criteria works
Set<Integer> setOrderNumbers = listCompletedOrders.stream().map(ModelCompletedOrders::getOrderNumber).collect(Collectors.toSet());
listOrders = listOrders.stream().filter(p -> !setOrderNumbers.contains(p.getOrderNumber()).collect(Collectors.toList());
// Below not working as expected when trying to combinational filter
Set<LocalDate> setDates = listCompletedOrders.stream().map(ModelCompletedOrders::getDate).collect(Collectors.toSet());
listOrders = listOrders.stream().filter(p -> !setDates.contains(p.getDate()) && !setOrderNumbers.contains(p.getOrderNumber()))
.collect(Collectors.toList());
You've asked for logic that will do this:
The combination of Date & Order Number is unique. I need to check if that unique combination is present in List-2, if yes then filter out, if not then output should contain that row.
Stream::filter() will return a subset of the stream where the filter predicate returns true (i.e. it filters out those objects in the stream where the predicate is false).
listOrders = listOrders.stream().filter(p -> !setDates.contains(p.getDate()) && !setOrderNumbers.contains(p.getOrderNumber()))
.collect(Collectors.toList());
Your code expression here says "show me orders where the order's date does not appear in the list of prior orders AND where the order's order number does not appear in the list of prior orders". Your logical expression is wrong (you're getting confused between what in electronics would be called positive vs negative logic).
You want either:
listOrders = listOrders.stream().filter(p -> !(setDates.contains(p.getDate()) && setOrderNumbers.contains(p.getOrderNumber())))
.collect(Collectors.toList());
"show me orders where both the order's date and order's id are not
present in the list of prior orders"
or:
listOrders = listOrders.stream().filter(p -> !setDates.contains(p.getDate()) || !setOrderNumbers.contains(p.getOrderNumber()))
.collect(Collectors.toList());
"show me orders where either the order's date has not been seen before
OR the order's id has not been seen before"

How to add a column of counts to an ArrayList

I have:
TAG | REVIEW
A | hello
B | yay
A | win
in an ArrayList and I am trying to get:
TAG | COUNT
A | 8 //hello+win =8
B | 3 //yay =3
where count is the total number of characters in all strings with the same tag. I have been reading about Collections and Maps, but I am completely lost. Can someone explain how to solve this in pieces?
1) To get the count:
List<String,Integer> poll_reviewText_count=new ArrayList<>();
for(String l:poll_reviewText){
poll_reviewText_count.add({l[0],l[1].length()}) //TAG, COUNT
}
2) Then I think I need to combine all the instances of TAG that match into one sum. Not sure how to do this.
There isn't such thing as List<V, T> in java. Also you can't use a Map for your data, because inserting this :
TAG | REVIEW
A | hello
B | yay
A | win
In map, A | hello will get replaced by A | win (they have the same key).
A solution will be to create a class that will contain TAG and REVIEW information:
class Bar {
String tag;
String review;
// setters - getters
}
And then using the java stream, you can collect the data how you want:
Map<String, Integer> collect = poll_reviewText_count.stream()
.collect(Collectors.groupingBy(Bar::getTag, Collectors.summingInt(o -> o.getReview().length())));

Hibernate Search Facet on multiple fields

Let's assume a have an index with multiple fields created from #Indexed entities:
----------------------------------
| FieldA | FiedlB | FieldC | ... |
----------------------------------
| AX | BX | other | ... |
----------------------------------
| AZ | BZ | value | ... |
----------------------------------
Would it be possible to construct a facet aggregating values from two fields?
For example - A_&_B:
AX
AZ
BX
BZ
Any other options possible?
I think your best bet is to define a method aggregating the values of both fields and annotate this method to index it as a facet.
Something like:
#Field(bridge = #FieldBridge(impl = CollectionOfStringsFieldBridge.class), analyze = Analyze.NO)
#Facet
public List<String> getAggregatedField() {
return yourAggregatedValue;
}
With CollectionOfStringsFieldBridge being something like: https://github.com/hibernate/hibernate-search/blob/master/orm/src/test/java/org/hibernate/search/test/embedded/fieldoncollection/CollectionOfStringsFieldBridge.java
It's better than aggregating the facet values returned by Lucene manually.

NullPointerException in a 3D Matrix of two custom Classes in Java [duplicate]

1 public class TestWin{
2 public static void main(String[] args){
3 int n;
4 hexagon[][] board;
5
6 n = 4;
7 board = new hexagon[n][n];
8 board[0][0].value = 'R';
Hi. javac doesn't like what I did on line 8. Does anyone know why?
It's been a while since I've so much as looked at Java, but have you tried doing this first?
board[0][0] = new hexagon(); // or whatever its constructor is
Spot on kwatford. All you have done with line 7 is to tell java to create space for n*n Hexagon objects in a 2 dimensional array.
You will still need to call new for each of these Hexagons
Essentially, you need to replace line 7 with something like:
board = new Hexagon[n][n];
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
board[i][j] = new Hexagon();
Short Answer:
As kwatford said what you need to do is this:
board[0][0] = new hexagon(); // or whatever its constructor is
Longer Explanation:
Just to expand further. Your 2D array is; an array of pointers (or references in Java). This is what one row of the array will look like immediately after this call board = new hexagon[n][n];:
0 1 2 3 4 5 // column index, row index = 0
-------------------------------------------
| | | | | | | | | | // value
--- | ----- | ----- | ---------------------
| | | ...
| | |
| | |
| | |
| | v
| | Null
| v
| Null
v
Null (This means that it points to nothing)
You tried:
board[0][0].value = 'R';
which is the same as this:
null.value = 'R';
You have initialized your array using this line:
board = new Hexagon[n][n];
But you still need to initialize the elements in your array. This would initialize the first three:
board[0][0] = new hexagon(); // or whatever its constructor is
board[1][0] = new hexagon(); // or whatever its constructor is
board[2][0] = new hexagon(); // or whatever its constructor is
Which would result in an array that looks like this:
0 1 2 3 4 5 // column index, row index = 0
-------------------------------------------
| | | | | | | | | | // value
--- | ----- | ----- | ---------------------
| | |
| | |
| | |
| | |
| | v
| | An instance of type Hexigoon (what you get when you type new Hexigon)
| v
| An instance of type Hexigon (what you get when you type new Hexigon)
v
An instance of type Hexigon (what you get when you type new Hexigon)
I remember banging my head on the table with this exact problem two years ago. I love stackoverflow
To expand on what kwatford said, initializing an array in java gives you nulls if the array type is an object. If you had a raw array, such as an array of doubles, you would start with 0 as the entry for each element of the array.

How to ensure first keys in all containers are unique in whole stack

I have a two command "add" and "undo". With "add" operation, more than one, including one, pair can be sent to the program. On the other hand, with "undo" operation, last sent data should be given back. To implement this functionality, I have thought;
I should have these elements of data structure;
| | HashMap<String, String> : It is used for storing data
| |
| |
| |
--------
Stack : It seems best to "undo" and "add" operations.
At some point, I should, in practice, have below stack;
| |
| |
| ________________________________ |
| | (filename5, date1) | | third HashMap type container
| | (filename6, date5) | | holding three items
| | (filename7, date9) | |
| |______________________________| |
| |
| ________________________________ | second HashMap type container
| | (filename3, date2) | | holding one item
| |______________________________| |
| |
| ________________________________ | first HashMap type container
| | (filename1, date1) | | holding two items
| | (filename2, date2) | |
| |______________________________| |
|----------------------------------|
My question is "How can I ensure first keys in all containers are unique in the whole stack?"
If it is not possible with above data structures, what should I use as a data structure to implement mentioned wish?
Why not just keeping two structures: Stack<String> and check, whether it contains or not filename_x, and second structure - your hashmap HashMap<String, String>?
UPD: In other words, you do not need to hold theese maps inside stack as its elements.
It is solved with three Java Stack, and own stack implementation to make push and pop operations synhronized. Implementation is ;
class OwnStack{
private final Stack<String> file = new Stack<String>()
private final Stack<String> date = new Stack<String>()
private final Stack<String> numberOfElementsPushedAtTheSamTime
= new Stack<String>()
public void push(String []files, String []date{
/* Algorithm
* Iterate over files
* if file is in stack
* donot push anything to stack
* else
* push file to stack
* push category to stack
* push number of entries pushed at the same time to stack (files.length())
*/
}
public void pop(){
/*
* Algorithm
* If size is zero in file stack
* do nothing
* else
* get top number from numberOfElementsPushedAtTheSamTime stack
* iterate over stacks returned number times
* pop files stack
* pop date stack
*/
// I donot need return values
}
}

Categories

Resources