I need to merge two lists of strings in java and I'm not too sure on the best way to do it. I have to use iterators and the compareTo() method. For example...
Example: L1: A,B,C,D L2: B,D,F,G result: A,B,B,C,D,D,F,G
I can assume the input lists are already sorted and i cant use the contains() method. I have some initial checks but the while loop is what im stuck on.
public static ListADT<String> merge(ListADT<String> L1,ListADT<String> L2) throws BadListException {
ListADT<String> L3 = new ArrayList<String>;
if(L1 == null || L2 == null) {
throw new BadListException();
}
Iterator<String> itr1 = new L1.iterator();
Iterator<String> itr2 = new L2.iterator();
if(L1.size() == 0 && L2.size() == 0) {
return L3;
}
if(L1.size() == 0 && L2.size() != 0) {
for(int i = 0; i < L2.size(); i++) {
return L3.add(L2.get(i));
}
}
if(L2.size() == 0 && L1.size() != 0) {
for(int i = 0; i < L1.size(); i++) {
return L3.add(L1.get(i));
}
}
while(itr1.hasNext() || irt2.hasNext()) {
//merge the lists here?
}
}
Any help would be appreciated.
It's fairly straightforward if you just use variables to hold the current value from each iterator. This solution assumes your lists do not contain null, but it would not be difficult to add null-handling since the lists are sorted.
package com.example;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
public class IteratorMerge {
/**
* #param args
*/
public static void main(String[] args) {
List<String> list1 = Arrays.asList(new String[]{"A", "B", "C", "D"});
List<String> list2 = Arrays.asList(new String[]{"B", "D", "F", "G"});
System.out.println(merge(list1, list2));
}
public static List<String> merge(List<String> L1,List<String> L2) {
List<String> L3 = new ArrayList<String>();
Iterator<String> it1 = L1.iterator();
Iterator<String> it2 = L2.iterator();
String s1 = it1.hasNext() ? it1.next() : null;
String s2 = it2.hasNext() ? it2.next() : null;
while (s1 != null && s2 != null) {
if (s1.compareTo(s2) < 0) { // s1 comes before s2
L3.add(s1);
s1 = it1.hasNext() ? it1.next() : null;
}
else { // s1 and s2 are equal, or s2 comes before s1
L3.add(s2);
s2 = it2.hasNext() ? it2.next() : null;
}
}
// There is still at least one element from one of the lists which has not been added
if (s1 != null) {
L3.add(s1);
while (it1.hasNext()) {
L3.add(it1.next());
}
}
else if (s2 != null) {
L3.add(s2);
while (it2.hasNext()) {
L3.add(it2.next());
}
}
return L3;
}
}
Here's some pseudocode for the basic algorithm:
while(itr1 && itr2)
{
if(itr1 value < it2 value)
add itr1 to list
increment itr1
else
add itr2 to list
increment itr2
}
check if itr1 or itr2 still have more elements
while itr1 or itr2 has more elements, add those elements to the list
We know that the lists are sorted, so at each stage, we simply grab the smallest element from each list and add it to the merged list. If, at the end, one of the iterators is exhausted and the other is not, then we can simply iterate through the one which still has elements, appending each element in turn to the merged list.
As you've seen, doing this with Iterators in Java is a bit of a pain as next() removes the element. One way of getting around this is to utilize two Queues, one for each Iterator, that store the values from the call to next(). You then need to compare the head of each queue, adding the minimum to the merged list and then removing it from its respective Queue.
As you've found, it is sort of a pain to merge using iterators. Let's explicitly state why:
For each step of the merge, you want to inspect the first element of both sequences, but you only want to advance through one.
Iterator#next() bundles these inspect and advance operations into one operation, so it is impossible to inspect the head of both sequences without also advancing through both.
What you need is a way to peek at the first element in an Iterator without advancing it. If you had this ability, then the merge would look something like:
public <T extends Comparable<T>> List<T> merge(Iterator<T> it1, Iterator<T> it2) {
PeekableIterator<T> seq1 = new PeekableIterator<T>(it1);
PeekableIterator<T> seq2 = new PeekableIterator<T>(it2);
List<T> merged = new ArrayList<T>();
while (seq1.hasNext() && seq2.hasNext()) {
if (seq1.peekNext().compareTo(seq2.peekNext()) < 0) {
merged.add(seq1.next());
} else {
merged.add(seq2.next());
}
}
while (seq1.hasNext()) {
merged.add(seq1.next());
}
while (seq2.hasNext()) {
merged.add(seq2.next());
}
return merged;
}
And it turns out that it is not too difficult to create this PeekableIterator! You just need to keep track of whether or not you currently have a peeked element, and what that element is.
public class PeekableIterator<T> implements Iterator<T> {
private final Iterator<T> backing;
private boolean havePeek = false;
private T peek;
public PeekableIterator(Iterator<T> backing) {
this.backing = backing;
}
#Override
public boolean hasNext() {
return havePeek || backing.hasNext();
}
#Override
public T next() {
if (havePeek) {
havePeek = false;
return peek;
} else {
return backing.next();
}
}
public T peekNext() {
if (!havePeek) {
peek = backing.next();
havePeek = true;
}
return peek;
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
}
EDIT
I didn't notice the comment above referring to the PeekingIterator in Google's Guava library, which is more or less the same as the PeekableIterator here. If you have access to third party libraries, this would certainly be preferable to rolling your own.
Don't try to manage merging of an empty list with a non empty one as a special case, just loop until at least one of the iterators is valid and do your work directly there:
public static ListADT<String> merge(ListADT<String> L1,ListADT<String> L2) throws BadListException {
ListADT<String> L3 = new ArrayList<String>;
Iterator<String> itr1 = new L1.iterator(), itr2 = new L2.iterator();
while (itr1.hasNext() || itr2.hasNext()) {
if (!itr1.hasNext())
L3.add(itr2.next());
else if (!itr2.hasNext())
L3.add(itr1.next());
else {
String s1 = peek from itr1
String s2 = peek from itr2;
if (s1.compareTo(s2) < 0) {
L3.add(itr1.next());
L3.add(itr2.next());
}
else {
L3.add(itr2.next());
L3.add(itr1.next())
}
}
}
}
public class MergeIterator {
public static void main(String[] args) {
List<String> s1 = new ArrayList<String>();
s1.add("a");
s1.add("z");
s1.add("b");
s1.add("k");
s1.add("c");
Collections.sort(s1);
List<String> s2 = new ArrayList<String>();
s2.add("p");
s2.add("a");
s2.add("d");
s2.add("n");
s2.add("m");
Collections.sort(s2);
Iterator<String> it1 = s1.iterator();
// sortIterator(it1);
Iterator<String> it2 = s2.iterator();
System.out.println();
combine(it1, it2);
}
private static Iterator<String> combine(Iterator<String> it1,
Iterator<String> it2) {
Iterator<String> it3 = null;
List<String> l1 = new ArrayList<>();
String s1 = null, s2 = null;
while (it1.hasNext() || it2.hasNext()) { //line 1
s1 = (s1 == null ? (it1.hasNext() ? it1.next() : null) : s1); //line 2
s2 = (s2 == null ? (it2.hasNext() ? it2.next() : null) : s2); // line 3
if (s1 != null && s1.compareTo(s2) < 0) { // line 4
l1.add(s1);
s1 = null;
} else {
l1.add(s2);
s2 = null;
}
}
it3 = l1.iterator();
return it3;
}
}
Related
For the exam, I train to write the some algorithms to the final exam. One of them is creating the reverse() method, which removes doubles in the List<> . The problem that the void method only removes one double or two. How can I change the method?
Here, the code of the List.java file. The methods removeFromBack(), removeFromFront(), insertAtBack(), insertAtFront(), print(), isEmpty(), the classes List and ListNode are already defined in Deitel's Java book. Additionally, all imports are done:
public void removeDuplicates() {
ArrayList<T> toCheck = new ArrayList<T>();
ListNode<T> current = firstNode;
while (current != null) {
toCheck.add(current.data);
current = current.nextNode;
}
current = firstNode;
HashSet<T> toCheck2 = new LinkedHashSet<T>();
for (T element: toCheck) {
toCheck2.add(element);
}
for (T element: toCheck2) {
removeFromBack();
insertAtBack(element);
}
}
you can add duplicates list and remove them like this:
public void removeDuplicates() {
ArrayList<T> elements = new ArrayList<T>();
ListNode<T> current = firstNode;
while (current != null) {
if(!elements.contains(current.data))
toCheck.add(current.data);
else {
// you have the duplicates, do your logic
}
current = current.nextNode;
}
}
There are faster/more efficient ways depending on your needs but this one should basically always work:
public static <T> ArrayList<T> removeDuplicates(ArrayList<T> toCheck) {
ArrayList<Integer> toRemove = new ArrayList<Integer>();
for(int i = 0; i < toCheck.size(); i++) {
T current = toCheck.get(i);
for(int j = 0; j < toCheck.size(); j++) {
if(j == i)continue;
if(toCheck.get(j) == current) {
toRemove.add(j);
}
}
}
Collections.sort(toRemove, Collections.reverseOrder());
for(int i : toRemove) {
toCheck.remove(i);
}
return toCheck;
}
For duplicates in List, you could always use Set to help to remove the duplicates:
public List<Integer> removeDuplicates(List<Integer> list) {
Set<Integer> set = new HashSet<>(list); // remove all duplicates in set
List<Integer> result = new ArrayList(set.size());
for (Integer i : list) {
if (set.contains(i)) {
result.add(i);
set.remove(i); // delete, so duplicate item will not be added to result twice
}
}
return result;
}
This question already has answers here:
How do I remove repeated elements from ArrayList?
(40 answers)
Closed 3 years ago.
List list = ["f1,f2","f2,f3","f4,f5","f2,f1","f5,f4"];
output list would be
List uniqueList = ["f1,f2","f2,f3","f4,f5"]
I have another solution . If you dont want to prepare another class to compare values inside List . You can separete each value by comma and sort those data. After that you can again converte them to Set of String
public static void main(String[] args) {
List<String> stringList = Arrays.asList("f1,f2", "f2,f3", "f4,f5", "f2,f1", "f5,f4");
Set<String> result = new HashSet<>();
for (String s : stringList) {
String[] elements = s.split(",");
Arrays.sort(elements);
result.add(Arrays.toString(elements));
}
for (String e : result){
System.out.println(e);
}
}
Using an additional class:
static class Pair {
String a, b;
Pair(String s) {
String[] arr = s.split(",");
this.a = arr[0];
this.b = arr[1];
}
static String pairToString(Pair p) {
return p.a + "," + p.b;
}
#Override
public int hashCode() {
return Objects.hash(a, b) + Objects.hash(b, a);
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Pair p = (Pair) o;
return (p.a.equals(a) && p.b.equals(b)) || (p.b.equals(a) && p.a.equals(b));
}
}
Now you can use:
public static void main(String[] args) {
List<String> list = Arrays.asList("f1,f2", "f2,f3", "f4,f5", "f2,f1", "f5,f4");
List<String> strings = list
.stream()
.map(Pair::new)
.distinct()
.map(Pair::pairToString)
.collect(Collectors.toList());
}
I have created a class to model the pairs and override the equals method to treat "f1,f2" and "f2,f1" as equals and then found out the duplicates using HashSet.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
public class so1 {
public static void main(String[] args) {
List<String> list = Arrays.asList(new String[] {"f1,f2","f2,f3","f4,f5","f2,f1","f5,f4"});
List<pair> plist = new ArrayList<pair>();
for (int i = 0; i < list.size(); i++) {
plist.add(new pair(list.get(i)));
}
HashSet<pair> hs = new HashSet<pair>();
for (int i = 0; i < plist.size(); i++) {
if(!hs.add(plist.get(i))){
System.out.println("Found duplicate "+plist.get(i).toString());
}
}
List<String> uniqueItems = new ArrayList<String>();
for (Iterator iterator = hs.iterator(); iterator.hasNext();) {
pair pair = (pair) iterator.next();
uniqueItems.add(pair.toString());
}
System.out.println(uniqueItems);
}
}
class pair{
pair(String inp){
String[] tokens = inp.split(",");
Arrays.sort(tokens);
for(String t: tokens){
elements.add(t);
}
}
List<String> elements = new ArrayList<>();
#Override
public String toString() {
return ""+elements;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((elements == null) ? 0 : elements.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
pair other = (pair) obj;
if (elements == null) {
if (other.elements != null)
return false;
} else if (!elements.equals(other.elements))
return false;
return true;
}
}
Here are a couple answers from https://www.geeksforgeeks.org/how-to-remove-duplicates-from-arraylist-in-java/
Java 7
// Create a new ArrayList
ArrayList<String> uniqueList = new ArrayList<String>();
// Traverse through the first list
for ( element : list) {
// If this element is not present in uniqueList
// then add it
if (!uniqueList.contains(element)) {
uniqueList.add(element);
}
}
Java 8
List<String> uniqueList = list.stream()
.distinct()
.collect(Collectors.toList());
I have a need to place null objects at the end of the List. Here is a sample what I have done for this purpose:
public static void main(String... args) {
List<String> strings = Arrays.asList(new String[]{"A", null, "B"});
for(String string : strings) {
System.out.println(string);
}
System.out.println("==================");
List<String> result = new ArrayList<String>();
List<String> nullStrings = new ArrayList<String>();
for(String string : strings) {
if(string != null) {
result.add(string);
} else {
nullStrings.add(string);
}
}
result.addAll(nullStrings);
for(String string : result) {
System.out.println(string);
}
}
I am looking forward to a more efficient and intelligent way to do this. Is it possible to swap inside the actual list so that null node get placed at the end, so that I don't need the other two list(nullStrings, result) and extra iteration.
Update
Sorting will not work for my case. This sample code I made just for testing purpose. Actually I have a different type of Object. Also Sorting will break the position.
Say I have this null, Obj2, Obj1, if do anything like sorting it may happens Obj1, Obj2, null. But I need Obj2, Obj1, null.
You can sort it using Collections.sort and a custom Comparator.
Here the compare code:
#Override
public int compare(String left, String right) {
if (left == right) {
return 0;
}
if (left == null) {
return 1;
}
if (right == null) {
return -1;
}
return 0;
}
Note that elements that have an equal value according to this Comparator won't be re-ordered. From Collections.sort:
This sort is guaranteed to be stable: equal elements will not be reordered as a result of the sort.
Just move non-null elements to the front and fill the rest of the list with null.
int j = 0;
for (int i = 0; i < strings.size(); i++)
if (strings.get(i) != null){
strings.set(j, strings.get(i));
j++;
}
for (; j < strings.size(); j++)
strings.set(j, null);
If you are using LinkedList (or something not a RandomAccess), you'll need ListIterator
ListIterator<String> j = strings.listIterator();
for (ListIterator<String> i = strings.listIterator(); i.hasNext();) {
String s = i.next();
if (s != null) {
j.next();
j.set(s);
}
}
while (j.hasNext()) {
j.next();
j.set(null);
}
The general strategy looks fine to me. I would bring the following changes:
initialize the result list with the appropriate size
don't use a separate list for nulls. At the end of the iteration, you just need to compare the length of the initial list with the length of the result list to know how many nulls you need to add.
Although making a copy of the list will use more memory, it could well be faster than changing the initial list, because removing elements needs to move all the subsequent elements each time. And sorting is N*log(N), whereas copying elements is O(N).
[EDIT owlstead]
public static List<String> moveNullsToEnd(final List<String> strings) {
final List<String> newStrings = new ArrayList<String>(strings.size());
for (String string : strings) {
if (string != null) {
newStrings.add(string);
}
}
for (int i = 0, remaining = strings.size() - newStrings.size(); i < remaining; i++) {
newStrings.add(null);
}
return newStrings;
}
Below code you can use
Remove all the null elements
int noOfNull =0 ,i=0;
for(; i< strings.size() ; i++)
{
if(strings.get(i) == null)
{
noOfNull++;
}
}
strings.removeAll(Collections.singleton(null));
Filling the array with null after the not null elements
for(i =strings.size(); i < strings.size()+noOfNull ; i++)
{
strings.add(null);
}
List<String> list = new ArrayList<>();
list.add("BR64");
list.add("SWG620");
list.add("");
list.add("sw0");
list.add("R124");
list.add("R219");
list.add("TaGh20");
list.add("SW6505");
list.add("");
list.add(null);
list.add("SW_6505");
list.add("swd_157");
list.add("localhost");
list.add("qaGh20_241");
list.add("gen");
list.add(null);
list.add("taGh20");
list.add("zen");
list.add("QWG");
list.add("SWG62_");
list.add("SWG620");
Collections.sort(list, new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
if (o1 != null && o2 != null && o1.length() > 0 && o2.length() > 0) {
return (Character.toLowerCase(o1.charAt(0)) == Character.toLowerCase(o2.charAt(0)))
? o1.compareTo(o2)
: (Character.toLowerCase(o1.charAt(0)) + o1.substring(1))
.compareTo((Character.toLowerCase(o2.charAt(0)) + o2.substring(1)));
} else {
return (o1 == o2) ? 0 : ((o1 == null || o1 == "") ? 1 : -1);
}
}
});
System.out.println(list);
Output-: [BR64, gen, localhost, QWG, qaGh20_241, R124, R219, SW6505, SWG620, SWG620, SWG62_, SW_6505, sw0, swd_157, TaGh20, taGh20, zen, , , null, null]
I have two list **ListA<MyData> listA = new ArrayList<MyData>()** and ListB<MyData> listB = new ArrayList<MyData>() both contain object of type MyData and MyData contain these variables.
MyData {
String name;
boolean check;
}
ListA and ListB both contains MyData objects ,now I have to compare both the list's object values here name as well check variable like if ListA contains these object values
ListA = ["Ram",true],["Hariom",true],["Shiv",true];
and ListB also contain
ListB = ["Ram",true],["Hariom",true],["Shiv",true];
then i have to compare lists and return false because both list are same
But if ListA contains
ListA = ["Ram",true],["Hariom",true],["Shiv",false];
and ListB Contain
ListB = ["Ram",true],["Hariom",true],["Shiv",true];
then I have to compare lists and return true because both list are not same
or vice-versa so any slight change in the any list values I have to return true.
One thing I have to mentioned here objects can be in any order.
It's not the most efficient solution but the most terse code would be:
boolean equalLists = listA.size() == listB.size() && listA.containsAll(listB);
Update:
#WesleyPorter is right. The solution above will not work if duplicate objects are in the collection.
For a complete solution you need to iterate over a collection so duplicate objects are handled correctly.
private static boolean cmp( List<?> l1, List<?> l2 ) {
// make a copy of the list so the original list is not changed, and remove() is supported
ArrayList<?> cp = new ArrayList<>( l1 );
for ( Object o : l2 ) {
if ( !cp.remove( o ) ) {
return false;
}
}
return cp.isEmpty();
}
Update 28-Oct-2014:
#RoeeGavriel is right. The return statement needs to be conditional. The code above is updated.
ArrayList already have support for this, with the equals method. Quoting the docs
...
In other words, two lists are defined to be equal if they contain the same elements in the same order.
It does require you to properly implement equals in your MyData class.
Edit
You have updated the question stating that the lists could have different orders. In that case, sort your list first, and then apply equals.
I got this solution for above problem
public boolean compareLists(List<MyData> prevList, List<MyData> modelList) {
if (prevList.size() == modelList.size()) {
for (MyData modelListdata : modelList) {
for (MyData prevListdata : prevList) {
if (prevListdata.getName().equals(modelListdata.getName())
&& prevListdata.isCheck() != modelListdata.isCheck()) {
return true;
}
}
}
}
else{
return true;
}
return false;
}
EDITED:-
How can we cover this...
Imagine if you had two arrays "A",true "B",true "C",true and "A",true "B",true "D",true. Even though array one has C and array two has D there's no check that will catch that(Mentioned by #Patashu)..SO for that i have made below changes.
public boolean compareLists(List<MyData> prevList, List<MyData> modelList) {
if (prevList!= null && modelList!=null && prevList.size() == modelList.size()) {
boolean indicator = false;
for (MyData modelListdata : modelList) {
for (MyData prevListdata : prevList) {
if (prevListdata.getName().equals(modelListdata.getName())
&& prevListdata.isCheck() != modelListdata.isCheck()) {
return true;
}
if (modelListdata.getName().equals(prevListdata.getName())) {
indicator = false;
break;
} else
indicator = true;
}
}
}
if (indicator)
return true;
}
}
else{
return true;
}
return false;
}
First, implement the MyData.equals(Object o) and MyData.hashCode() methods.
Once you implemented the equals method, you can iterate over the lists as follows:
if(ListA == null && ListB == null)
return false;
if(ListA == null && ListB != null)
return true;
if(ListA != null && ListB == null)
return true;
int max = ListA.size() > ListB.size() ? ListA.size() : ListB.size();
for(int i = 0; i < max; i++) {
myData1 = ListA.get(i);
myData2 = ListB.get(i);
if(!myData1.equals(myData2)) {
return true;
}
}
return false;
I found a very basic example of List comparison at List Compare
This example verifies the size first and then checks the availability of the particular element of one list in another.
This can be done easily through Java8 using forEach and removeIf method.
Take two lists. Iterate from listA and compare elements inside listB
Write any condition inside removeIf method.
Hope this will help
listToCompareFrom.forEach(entity -> listToRemoveFrom.removeIf(x -> x.contains(entity)));
Override the equals method in your class and use Collection#equals() method to check for equality.
See if this works.
import java.util.ArrayList;
import java.util.List;
public class ArrayListComparison {
public static void main(String[] args) {
List<MyData> list1 = new ArrayList<MyData>();
list1.add(new MyData("Ram", true));
list1.add(new MyData("Hariom", true));
list1.add(new MyData("Shiv", true));
// list1.add(new MyData("Shiv", false));
List<MyData> list2 = new ArrayList<MyData>();
list2.add(new MyData("Ram", true));
list2.add(new MyData("Hariom", true));
list2.add(new MyData("Shiv", true));
System.out.println("Lists are equal:" + listEquals(list1, list2));
}
private static boolean listEquals(List<MyData> list1, List<MyData> list2) {
if(list1.size() != list2.size())
return true;
for (MyData myData : list1) {
if(!list2.contains(myData))
return true;
}
return false;
}
}
class MyData{
String name;
boolean check;
public MyData(String name, boolean check) {
super();
this.name = name;
this.check = check;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (check ? 1231 : 1237);
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MyData other = (MyData) obj;
if (check != other.check)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
You can subtract one list from the other using CollectionUtils.subtract, if the result is an empty collection, it means both lists are the same. Another approach is using CollectionUtils.isSubCollection or CollectionUtils.isProperSubCollection.
For any case you should implement equals and hashCode methods for your object.
Using java 8 removeIf to compare similar items
public int getSimilarItems(){
List<String> one = Arrays.asList("milan", "dingo", "elpha", "hafil", "meat", "iga", "neeta.peeta");
List<String> two = new ArrayList<>(Arrays.asList("hafil", "iga", "binga", "mike", "dingo")); //Cannot remove directly from array backed collection
int initial = two.size();
two.removeIf(one::contains);
return initial - two.size();
}
Logic should be something like:
First step: For class MyData implements Comparable interface, override the compareTo method as per the per object requirement.
Second step: When it comes to list comparison (after checking for nulls),
2.1 Check the size of both lists, if equal returns true else return false, continue to object iteration
2.2 If step 2.1 returns true, iterate over elements from both lists and invoke something like,
listA.get(i).compareTo(listB.get(i))
This will be as per the code mentioned in step-1.
It's been about 5 years since then and luckily we have Kotlin now.
Comparing of two lists now looks is as simple as:
fun areListsEqual(list1 : List<Any>, list2 : List<Any>) : Boolean {
return list1 == list2
}
Or just feel free to omit it at all and use equality operator.
I know it's old question but in case anyone needs it. I use this in my application and it works well. i used it to check if the cart has been changed or not.
private boolean validateOrderProducts(Cart cart) {
boolean doesProductsChanged = false;
if (originalProductsList.size() == cart.getCartItemsList().size()) {
for (Product originalProduct : originalProductsList) {
if (!doesProductsChanged) {
for (Product cartProduct : cart.getCartProducts()) {
if (originalProduct.getId() == cartProduct.getId()) {
if (originalProduct.getPivot().getProductCount() != cartProduct.getCount()) {
doesProductsChanged = true;
// cart has been changed -> break from inner loop
break;
}
} else {
doesProductsChanged = false;
}
}
} else {
// cart is already changed -> break from first loop
break;
}
}
} else {
// some products has been added or removed (simplest case of Change)
return true;
}
return doesProductsChanged;
}
String myData1 = list1.toString();
String myData2 = list2.toString()
return myData1.equals(myData2);
where :
list1 - List<MyData>
list2 - List<MyData>
Comparing the String worked for me. Also NOTE I had overridden toString() method in MyData class.
I think you can sort both lists and convert to List if some of them was a HashSet colleciton.
java.utils.Collections package lets you do it.
List<Category> categoriesList = new ArrayList<>();
Set<Category> setList = new HashSet<>();
Collections.sort(categoriesList);
List<Category> fileCategories = new ArrayList<>(setList);
Collections.sort(fileCategories);
if(categoriesList.size() == fileCategories.size() && categoriesList.containsAll(fileCategories)) {
//Do something
}
I'm trying to write a method that will take in two Queues (pre-sorted Linked Lists) and return the merged, in ascending order, resulting Queue object. I pasted the Queue class, the merge method starts 1/2 way down.
I'm having trouble calling merge, this is how I am trying to call it from my main method, can anyone help with this call with new1 and new2. Thanks so much Everyone!
Please let me know if anyone notices anything else out of place. Thanks!
///////////////// //Testing with a call of merge method & 2 Queues///////////////////
public class test {
public static void main (String args[]){
Queue new1 = new Queue();
new1.enqueu(1);
new1.enqueu(3);
new1.enqueu(5);
Queue new2 = new Queue();
new1.enqueu(2);
new1.enqueu(4);
new1.enqueu(6);
merge(new1, new2);
//How to call merge? Queue.merge(new1, new2)???
/////////////////Queue/Merge method below////////////////////////
public class Queue {
private Node first, last;
public Queue(){
first = null;
last = null;
}
public void enqueu(int n){
Node newNode = new Node(n);
if (first == null)
{
first = newNode;
last = newNode;
}
else
{
last.setNext(newNode);
last = newNode;
}
}
public int dequeue(){
int num = first.getNum();
first = first.getNext();
if(first == null)
last = null;
return num;
}
public Boolean isEmpty() { return first == null; }
////////////////////////Begin Queue merge/////////////////////////////////
Queue merge(Queue q1, Queue q2) {
Queue result = new Queue();
boolean q1empty = q1.isEmpty();
boolean q2empty = q2.isEmpty();
while (!(q1empty || q2empty)) {
if (q1.first.getNum() < q2.first.getNum()) {
result.enqueu(q1.dequeue());
q1empty = q1.isEmpty();
} else {
result.enqueu(q2.dequeue());
q2empty = q2.isEmpty();
}
}
if (!q1empty) {
do {
result.enqueu(q1.dequeue());
} while (!q1.isEmpty());
} else if (!q2empty) {
do {
result.enqueu(q2.dequeue());
} while (!q2.isEmpty());
}
return result;
}}
You have what appears to be a bug here:
Queue new1 = new Queue();
new1.enqueu(1);
new1.enqueu(3);
new1.enqueu(5);
Queue new2 = new Queue();
new1.enqueu(2);
new1.enqueu(4);
new1.enqueu(6);
You've added six elements to new1 and zero to new2.
Since your merge method is an instance method of the Queue class, you need to call it on an instance of Queue, such as
Queue q = new Queue();
Queue merged = q.merge(new1, new2);
However since merge appears to have no side-effects and does not alter any state of the Queue instance, you probably want to just make this method static so that it belongs to the Queue class and not an instance of Queue. For example:
static Queue merge(Queue q1, Queue q2) {
...
}
//in main()...
Queue merged = Queue.merge(new1, new2);
A simple approach to merging two sorted Iterators into another Iterator:
public static Iterator<Object> merge(final Iterator<Object> it1,
final Iterator<Object> it2, final Comparator<Object> comp) {
return new Iterator<Object>() {
private Object o1 = it1.hasNext() ? it1.next() : null, o2 = it2
.hasNext() ? it2.next() : null;
#Override
public boolean hasNext() {
return o1 != null || o2 != null;
}
#Override
public Object next() {
if (o1 == null && o2 == null)
throw new NoSuchElementException();
Object ret;
if (o1 == null) {
ret = o2;
o2 = it2.hasNext() ? it2.next() : null;
} else if (o2 == null) {
ret = o1;
o1 = it1.hasNext() ? it1.next() : null;
} else {
if (comp.compare(o1, o2) <= 0) {
ret = o1;
o1 = it1.hasNext() ? it1.next() : null;
} else {
ret = o2;
o2 = it2.hasNext() ? it2.next() : null;
}
}
return ret;
}
#Override
public void remove() {
throw new UnsupportedOperationException("Not implemented");
}
};
}