I want to sort the elements using Priority Queue in Java.
Here is my code. What is wrong in it?
import java.io.*;
import java.util.*;
class PQ {
static class IntCompare implements Comparator<Integer>{
#Override
public int compare(Integer arg0, Integer arg1) {
if(arg0 > arg1)
return -1;
else if(arg0 < arg1)
return 1;
else
return 0;
}
}
public static void main (String[] args) {
int a[] = { 1, 3, 8, 5, 2, 6 };
Comparator<Integer> c = new IntCompare();
PriorityQueue<Integer> pq=new PriorityQueue<>(c);
for(int i = 0; i < a.length; i++)
pq.add(a[i]);
System.out.println(pq);
}
}
my output is:
8, 5, 6, 1, 2, 3
correct output:
8, 6, 5, 3, 2, 1
When you call System.out.println(pq), the toString method is called implicitly.
The toString method of PriorityQueue extends from AbstractCollection, which
Returns a string representation of this collection. The string
representation consists of a list of the collection's elements in the
order they are returned by its iterator, enclosed in square brackets
("[]").
While the iterator of PriorityQueue is not guaranteed to traverse in particular order:
The Iterator provided in method iterator() is not guaranteed to
traverse the elements of the priority queue in any particular order.
since the queue is based on heap.
You can poll elements one by one to get ordered elements:
while (pq.size() != 0) {
System.out.print(pq.poll() + ","); // 8,6,5,3,2,1,
}
You should poll() all the elements until the queue is empty and save them somewhere to get them ordered.
Try the following, list contains items in sorted order. The priority key by itself not maintain the elements in sorted order, it just keeps the top element as minimum or maximum based on your implementation of the PQ.
public static void main (String[] args) {
int a[]={1,3,8,5,2,6};
Comparator<Integer> c = new IntCompare();
PriorityQueue<Integer> pq=new PriorityQueue<>(c);
for(int i=0;i<a.length;i++)
pq.add(a[i]);
ArrayList<Integer> list = new ArrayList<>();
while(!pq.isEmpty()){
list.add(pq.poll());
}
for(Integer i : list)
System.out.println(i);
}
Related
I have this method to merge 2 sorted arrays into one sorted array:
public void merge(T[] a, int l1, int r1, T[] b, int l2, int r2, T[] c, int l3) {
while (l1 < r1 && l2 < r2) {
if (a[l1].compareTo(b[l2]) < 0) {
c[l3++] = a[l1++];
} else
c[l3++] = b[l2++];
}
while (l1 < r1)
c[l3++] = a[l1++];
while (l2 < r2)
c[l3++] = b[l2++];
}
But now I want to do it with 4 arrays at once.
I tried really long to come up with a solution, but wasn’t really successful. Does somebody have an idea how to do it?
There is a much simpler way using Java8 streams than doing this by hand:
combine all arrays into one stream (i've used 2 but you can use as many as you want to):
int[] arr1 = {1, 7, 10};
int[] arr2 = {1, 2, 4, 9};
Stream<int[]> ints = Stream.of(arr1, arr2);
then flatMap and sort them in a stream:
IntStream intStream = ints.flatMapToInt(Arrays::stream).sorted();
and when you print them you will see all the numbers sorted:
intStream.forEach(System.out::println);
1
1
2
4
7
9
10
combined in a function, it could look something like this:
public int[] merge(int[]... arrays) {
return Stream.of(arrays)
.flatMapToInt(Arrays::stream)
.sorted()
.toArray();
}
EDIT: The advantage of streams is, that you can further modify the values as you like. e.g. by leveraging the distinct function you can easily remove duplicates:
intStream = intStream.distinct();
intStream.forEach(System.out::println);
1
2
4
7
9
10
I've generalized the problem to "merging N sorted arrays into a single sorted array".
The code provided in the question utilizes generics. But it introduces a problem because arrays are not type-safe. In short, there's a substantial difference in their behavior: arrays are covariant and, on the other hand, generics are invariant. Due to that, compiler will not be abler to identify a problem when generics and arrays are mixed. It's a good practice to avoid usage of generic arrays.
Also, I've taken into account that it is clearly an algorithmic problem (therefore its audience broader than readers who have a deep insight in Java, which is required to grasp generic-based implementation) I've decided to create two flavors of solution one using arrays exclusively, another with generics and Collections framework.
Non-generic version
Below is the description of how to merge an arbitrary number of sorted arrays of primitives:
find the total number of elements and create a resulting array based on it;
define an array that will maintain a current position in each of the source arrays;
using a nested for loop for each position in the resulting array, pick the lowest value of all currently accessible values.
The time complexity of this algorithm is O(n * m) (where n - is the total number of elements in all arrays and m is the number of arrays).
The implementation might look like this:
public static int[] mergeNSorted(int[]... arrays) {
int[] result = new int[getTotalLength(arrays)];
int[] positions = new int[arrays.length]; // position for each array
for (int pos = 0; pos < result.length; pos++) {
int minCurVal = Integer.MAX_VALUE;
int curArr = 0;
for (int i = 0; i < arrays.length; i++) {
if (positions[i] < arrays[i].length && arrays[i][positions[i]] < minCurVal) {
minCurVal = arrays[i][positions[i]];
curArr = i;
}
}
result[pos] = minCurVal;
positions[curArr]++;
}
return result;
}
public static int getTotalLength(int[][] arrays) {
long totalLen = 0;
for (int[] arr : arrays) totalLen += arr.length;
if (totalLen > Integer.MAX_VALUE) throw new IllegalArgumentException("total length exceeded Integer.MAX_VALUE");
return (int) totalLen;
}
main() - demo
public static void main(String[] args) {
int[][] input =
{{1, 3}, {}, {2, 6, 7}, {10}, {4, 5, 8, 9}};
System.out.println(Arrays.toString(mergeNSorted(input)));
}
Output
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Generic version
In this version, input considered to be a list containing multiple lists of generic type T which expected to implement Comparable interface.
This solution enhances the array-based implementation provided above, reducing the overall time complexity to O(n * log m) (where n - is the total number of elements in all arrays and m is the number of arrays).
Instead of performing m iteration for each resulting element it maintains a PriorityQueue, which in this case represents a Min-Heap (i.e. when a head element is being retrieved from it, it'll have the lowest value of all the elements that are present in the queue).
Every element in queue wraps the value of a particular element retrieved from one of the given lists, as well the data regarding the source of this value (i.e. an index of the list and a position inside this list).
This wrapper over the element of the nested list can be represented by the class shown below.
public class ElementWrapper<V extends Comparable<V>> implements Comparable<ElementWrapper<V>> {
private V value;
private int listIndex;
private int position;
public ElementWrapper(V value, int listIndex, int position) {
this.value = value;
this.listIndex = listIndex;
this.position = position;
}
// getters
#Override
public int compareTo(ElementWrapper<V> o) {
return value.compareTo(o.getValue());
}
}
Note, that this class implements the of Comparable interface based on the value of wrapped list element.
The queue is being prepopulated with the first element of each non-empty list. And then until the queue is not empty, its lowest element is being removed and gets added to the resulting list. Also, if a list to which the latest element retrieved from the queue points, has more elements, the next of them will be added into the queue.
Note that both operations of adding a new element into the priority queue add() and removing its head element remove() according to the documentation has a cost of O(n) time (where n is the number of elements in the queue).
The same time complexity can be achieved by utilizing a TreeSet instead, but in practice PriorityQueue will perform better because a heap is easier to maintain than a red-black tree.
The code might look like this:
public static <T extends Comparable<T>> List<T> mergeNSorted(List<List<T>> lists) {
List<T> result = new ArrayList<>();
Queue<ElementWrapper<T>> queue = getInitializedQueue(lists);
while (!queue.isEmpty()) {
ElementWrapper<T> next = queue.remove();
result.add(next.getValue());
if (next.getPosition() + 1 < lists.get(next.getListIndex()).size()) {
queue.add(new ElementWrapper<>(lists.get(next.getListIndex()).get(next.getPosition() + 1),
next.getListIndex(),
next.getPosition() + 1));
}
}
return result;
}
public static <T extends Comparable<T>> Queue<ElementWrapper<T>> getInitializedQueue(List<List<T>> lists) {
Queue<ElementWrapper<T>> queue = new PriorityQueue<>();
for (int i = 0; i < lists.size(); i++) {
if (lists.get(i).isEmpty()) continue;
queue.add(new ElementWrapper<>(lists.get(i).get(0), i, 0));
}
return queue;
}
main() - demo
public static void main(String[] args) {
List<List<Integer>> genericInput =
List.of(List.of(1, 3), List.of(), List.of(2, 6, 7), List.of(10), List.of(4, 5, 8, 9));
System.out.println(mergeNSorted(genericInput));
}
Output
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
I'm not a Java programmer so I'll just give Pythonesque pseudo-code.
First turn each non-emptyarray into a triplet:
(next_value, index, array)
Now put those into a priority queue sorted by next value.
while 0 < queue.size():
(next_value, index, array) = queue.poll()
answer.append(next_value)
if index+1 < array.length:
queue.add((array[index+1], index+1, array))
If you have k arrays, this will take O(log(k)) comparisons per element produced.
Sadly, Java does not seem to have anything corresponding to the swaptop method. I practice if one array has a run of values, using .peek() to get the top element then .swaptop(...) if you can will let you go through those runs with O(1) work per element.
This could also be an good example using List<String> in addition to int[]
import org.testng.annotations.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class TestClass {
public static List<String> list(String... elems) {
return new ArrayList<>(Arrays.asList(elems));
}
public static List<String> mergedListSorted(List<String>... listsVarArgs) {
return Stream.of(listsVarArgs).flatMap(List::stream).sorted().collect(Collectors.toList());
}
#Test
public void sortedListsTest() {
// Sorted sub lists
List<String> AGMS = list("A", "G", "M", "S");
List<String> BHNT = list("B", "H", "N", "T");
List<String> CIOU = list("C", "I", "O", "U");
List<String> DJPV = list("D", "J", "P", "V");
List<String> EKQW = list("E", "K", "Q", "W");
List<String> FLRX = list("F", "L", "R", "X");
System.out.println(mergedListSorted(AGMS, BHNT, CIOU, DJPV, EKQW, FLRX));
System.out.println(mergedListSorted(BHNT, BHNT, CIOU, BHNT));
}
}
The according output of two examples:
[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X]
[B, B, B, C, H, H, H, I, N, N, N, O, T, T, T, U]
I have created an Iterable in Java that sort keys by their occurrence in decending order. For example if I have this array: [3, 3, 3, 2, 2, 1] I will get the output 3 2 1. Though there is one problem with my code. Whenever the occurrence of a key appears twice it overwrites the old one. For example if i have this array: [3, 3, 3, 2, 2, 1, 1, 0] I will get the output 3 1 0 when I want ot get 3 2 1 0. Here is what my Iterable looks like:
Iterable<Key> keys()
{
ArrayList<Key> keyList = new ArrayList<>();
ArrayList<Integer> occurrenceList = new ArrayList<>();
Map<Integer, Key> sortedMap = new TreeMap<Integer, Key>();
ArrayList <Key> temp = new ArrayList<>();
int j = 0;
//puts keys in one arraylist and occurrences in another arraylist
for (int i = 1; i < size; i++)
{
if (keys[i] != null)
{
keyList.add((Key) keys[i].getKey());
occurrenceList.add(keys[i].counter);
}
}
//puts each key and occurrence in a treemap so that they are "linked"
//This is where the overwriting is happening
for(Integer num : occurrenceList)
{
sortedMap.put(occurrenceList.get(j), keyList.get(j));
j++;
}
//puts the key values in another arraylist in the sorted order from the sortedMap
for(Key s : sortedMap.values())
{
temp.add(s);
}
//flips it to decending order
Collections.reverse(temp);
return temp;
}
This is where the problem happens:
for(Integer num : occurrenceList)
{
sortedMap.put(occurrenceList.get(j), keyList.get(j));
j++;
}
And this is how i test my code:
public static void main(String[] args) {
LinearProbingHashSet<Integer> list = new LinearProbingHashSet<>(30);
list.insert(3);
list.insert(3);
list.insert(3);
list.insert(2);
list.insert(2);
list.insert(1);
for(int i : list.keys())
{
System.out.println(i);
}
}
It is also worth noting that I am not using a Key array but rather a HashElement array. Hashelement is my own class that looks like this:
public class HashElement<Key> implements Comparable<HashElement<Key>> {
Key key;
int counter;
HashElement(Key key)
{
this.key = key;
this.counter = 1;
}
HashElement(Key key, int counter)
{
this.key = key;
this.counter = counter;
}
int getFrequency()
{
return this.counter;
}
Key getKey()
{
return this.key;
}
public int compareTo(HashElement that) {
if(this.counter > that.counter)
{
return 1;
}
else if(this.counter < that.counter)
{
return -1;
}
else
{
return 0;
}
}
}
I know my code is probably not optimised but right now I want to focus on getting it to work. Also I am not 100% sure what I am doing. How would you go about fixing the overwrite problem?
The problem of your code lies in this statement:
sortedMap.put(occurrenceList.get(j), keyList.get(j));
Consider the array = [3,3,3,2,2,1,1,0], when this part executes
for (int i = 1; i < size; i++)
{
if (keys[i] != null)
{
keyList.add((Key) keys[i].getKey());
occurrenceList.add(keys[i].counter);
}
}
The keyList is [3, 2, 1, 0], and occurrenceList is [3, 2, 2, 1].
Now, when you try to put the elements of occurrenceList in a map, like this:
for(Integer num : occurrenceList)
{
sortedMap.put(occurrenceList.get(j), keyList.get(j));
j++;
}
The 2 at index-2 in occurrenceList, overrides in the map, the 2 at index-1, because Maps in Java, inserting a key twice will override its previous value, it will not store duplicate. You can do something like this:
for(Integer num : occurrenceList)
{
if(sortedMap.containsKey(num)){
sortedMap.get(num).add(keyList.get(j));
}else{
sortedMap.put(num, Arrays.asList(keyList.get(j)));
}
j++;
}
//puts the key values in another arraylist in the sorted order from the sortedMap
for(List<Key> s : sortedMap.values())
{
Collections.sort(s, new Comparator<Key>(){
public int compare(Key k1, Key k2){
return k1.getKey() - k2.getKey();
}
});
temp.addAll(s);
}
And declare sortedMap like this:
Map<Integer, List<Key>> sortedMap = new TreeMap<Integer, List<Key>>();
Here is one approach to demonstrate some concepts. I suggest you use it as a guide to understanding how the various capabilities work. Those can then be applied to your own solution. It is especially important to use the Java API Documentation to research the various Java API features and classes (streams, interfaces, comparators, etc) to understand how they are being used.
List<Integer> list1 =
List.of(3, 2, 5, 3, 3, 1, 0, 2, 5, 5, 5, 5, 0, 0, 2);
MySpecialSet<Integer> list = new MySpecialSet<>(list1);
// the enhanced for loop may be used because of the Iterable interface
for (int v : list) {
System.out.printf("%s ", v);
}
System.out.println();
// Using an array of Objects
Integer[] ints = { 1, 3, 3, 3, 2, 2, 4, 4, 4, 4, 6, 6, 6, 6,
6, 6, 5, 5, 5, 5, 5 };
MySpecialSet<Integer> list2 = new MySpecialSet<>(ints);
// This time using an explicit iterator.
Iterator<Integer> it = list2.iterator();
while (it.hasNext()) {
System.out.printf("%s ", it.next());
}
System.out.println();
prints
5 3 2 0 1
6 5 4 3 2 1
Here is the explanation of the class. This class will accept either an Array or a List of elements that implement the Comparable interface which is required for sorting of the elements.
this class implements the Iterable interface to return an Iterator. This allows the enhanced for loop to operate over the list.
when the iterator is obtained, either directly or implicitly, it converts the supplied list to meet the requirements.
first stream the keys and collect them in a map using a frequency count.
then stream the entryset of that map and sort based first on the frequency and if the frequencies are equal, then the key itself. And do these in reverse order.
then, the keys are returned in an internal list to be used by the iterator.
class MySpecialSet<T extends Comparable<T>> implements Iterable<T> {
private ArrayList<T> list;
public MySpecialSet(T[] v) {
list = new ArrayList<>(Arrays.asList(v));
}
public MySpecialSet(Collection<T> coll) {
this.list = new ArrayList<>(coll);
}
public Iterator<T> iterator() {
return new MyIterator();
}
private class MyIterator implements Iterator<T> {
private Iterator<T> it;
// comparator to direct the sort for comparing the may entries. First compare
// on the value (count) then if the count is equal, compare on the key
Comparator<Entry<T, Long>> comp = Entry
.<T, Long>comparingByValue()
.thenComparing(Entry.comparingByKey()).reversed();
public MyIterator() {
// This will essentially be a set since no duplicate
// entries will be present
List<T> result = list.stream()
// frequency count and collect into map
.collect(Collectors.groupingBy(k -> k,
Collectors.counting()))
// then stream the entries and sort as explained
// above using comparator.
.entrySet().stream().sorted(comp)
// then collect the keys into a list
.map(Entry::getKey).collect(Collectors.toList());
it = result.iterator();
}
// simply use the iterator of the newly created list.
public boolean hasNext() {
return it.hasNext();
}
public T next() {
return it.next();
}
}
}
I want to duplicate the elements in a linked list. This is what I have tried:
public class duplicate {
public static void main(String[] args) {
LinkedList <Integer> list = new LinkedList<Integer>() ;
list.add(2);
list.add(3);
list.add(4);
list.add(1);
list.add(0);
for( int i= 0 ; i<list.size(); i++) {
list.addAll(list);
System.out.println(list);
break;
}
}
}
But I got an infinite loop.
Firstly, your code runs just fine (the break prevents the infinite loop, see JLS-The break Statement).
Now, you don't need to for-loop over the list because List.addAll already
Appends all of the elements in the specified collection to the end of
this list, in the order that they are returned by the specified
collection's iterator (optional operation) (...)
So, just by doing this you're fine:
LinkedList <Integer> list = new LinkedList<Integer>() ;
//... code omitted (adds every number)
list.addAll(list);
However, if you want to use List.add instead of List.addAll you can do it like this (need to use for-loop):
LinkedList <Integer> list = new LinkedList<Integer>() ;
//... code omitted (adds every number)
int initialSize = list.size();
for( int i = 0 ; i < initialSize; i++) {
list.add(list.get(i));
}
System.out.println(list);
you are adding the list elements again and again in the for loop.
for(int i= 0 ; i < list.size(); i++) {
list.addAll(list);
System.out.println(list);
}
Every time it will grow & which leads the size to grow for each iteration. correct the step. Either use a local variable to store the size or change your logic
You can simply do list.addAll(list);.
If you want to use the add method as an exercise, you need to be careful to save the original size of the list before you start iterating. You can do it in the initialization part of your for loop:
public static void main(String[] args) {
List<Integer> list = new ArrayList<>(Arrays.asList(2, 3, 4, 1, 0));
for (int i = 0, size = list.size(); i < size; i++)
list.add(list.get(i));
System.out.println(list);
assert list.equals(Arrays.asList(2, 3, 4, 1, 0, 2, 3, 4, 1, 0));
}
Now you'll notice the above uses ArrayList, rather than LinkedList. In general, you should prefer ArrayList. Even the author of Java's LinkedList says he doesn't use it. See also this SO question about ArrayList vs LinkedList.
If you have to use LinkedList, you can just replace the second line from the above to this:
List<Integer> list = new LinkedList<>(Arrays.asList(2, 3, 4, 1, 0));
The rest of the code can remain unchanged. However, if you have a very long list, then using the get(index) method of the LinkedList class can reduce performance. With LinkedList, you get higher performance if you iterate (using LinkedList.iterator() or an enhanced for loop, than by using a plain for loop with get() calls. But you can't iterate over the list while adding to it, as you'll then get a ConcurrentModificationException. Instead, you can copy the linked list to an array and iterate over that, while adding to the list:
public static void main(String[] args) {
List<Integer> list = new LinkedList<>(Arrays.asList(2, 3, 4, 1, 0));
for (Integer element : list.toArray(new Integer[0])) {
list.add(element);
}
System.out.println(list);
assert list.equals(Arrays.asList(2, 3, 4, 1, 0, 2, 3, 4, 1, 0));
}
I used to thing that HashSet is a pretty fast data structure implementation because it uses hashes (and is implemented via HashMap in its turn).
I was solving some problems and decided to check performance issue, so here it is:
You are given an array with numbers - [11, 3, 11, 11, 3, 2, 0, -2, 2]
You are supposed to write a function that returns the number that appears "odd" number of times.
Here is my solution:
public class OddNumInArray {
public static List<Integer> oddNumList(int [] ar){
Collection <Integer> l = new ArrayList<>();
for (int n: ar) {
if (l.contains(n)) {
l.remove(n);
}
else {
l.add(n);
}
}
return (List) l;
}
public static Set<Integer> oddNumHSet(int [] ar){
Set <Integer> l = new HashSet<>();
for (int n: ar) {
if (l.contains(n)) {
l.remove(n);
}
else {
l.add(n);
}
}
return l;
}
public static void main(String [ ]arg) {
int [] a1 = new int [10000000];
for (int i=0; i<10; i++){
a1[i]=(new Random()).nextInt(5);
}
long cur= System.nanoTime();
System.out.println(oddNumList(a1));
long c1 = System.nanoTime()-cur;
System.out.println("TIME CONSUMED:" +c1);
cur= System.nanoTime();
System.out.println(oddNumHSet(a1));
long c2 = System.nanoTime()-cur;
System.out.println("TIME CONSUMED:" + c2);
System.out.println("c1/c2*100: "+ (new Double(c1)/new Double(c2)*100));
}
}
And here is an output:
[1, 0]
TIME CONSUMED:101804000
[0, 1]
TIME CONSUMED:183261000
c1/c2*100: 55.55137208680516
So, why is implementation with ArrayList is quicker than one with HashSet by almost 2 times?
Thank you.
ArrayList doesn't have code to check for duplicates. So, it just adds elements as and how you try to add them. A HashSet on the other hand is meant to have only unique elements, so it makes a check to prevent insertion of duplicate elements.
The following Java code:
public static void main(String args[]) {
int[] x = new int[] {1, 2, 3};
int[] y = new int[] {1, 2, 3};
LinkedList<int[]> list = new LinkedList<int[]>();
list.add(x);
System.out.println("List contains y: " + list.contains(y));
}
gives the output
List contains y: false
which makes sense as x and y are references to different memory locations, however there is also a sense in which they are equal (they have the the same elements in the same order).
Is there a data structure which would return true to the query list.contains(y) in this example?
I don't believe there is a Java data structure that would return true for contains() as you have described.
The issue, as you probably know, is that for Java arrays, equals() only tests for Object identity and not "equality" as most would define it.
Since contains() relies on equals() in this case (and most of the time), you're stuck with the given behaviour.
You would have to implement a List that specifically overrode contains() to provide your desired behaviour for Java arrays, probably using Arrays.equals().
My suggestion is to instead use a List instead of an array; you'd then have a List<List<Integer>>. contains() should work in this scenario as it'll use equals() on the underyling List implementation.
You need to define a comparator for your arrays. Then when the list looks up the elements, it will use your comparator to see if they're the same:
public static void main(String args[]) {
int[] x = new int[] {1, 2, 3};
int[] y = new int[] {1, 2, 3};
LinkedList<int[]> list = new LinkedList<int[]>(new Comparator<int[]>() {
#Override
public int compare(int[] a1, int[] a2) {
if(a1 == a2) return 0;
if(a1 == null && a2 != null) return -1;
if(a1 != null && a2 == null) return 1;
if(a1.size() < a2.size()) return -1;
if(a1.size() > a2.size()) return 1;
for(int i = 0; i < a1.size(); i++) {
int comp = a1[i] - a2[i];
if(comp < 0) return -1;
if(comp > 0) return 1;
}
return 0;
}
});
list.add(x);
System.out.println("List contains y: " + list.contains(y));
}
It looks like you're really looking for a Set implementation.
A collection that contains no duplicate elements. More formally, sets contain no pair of elements e1 and e2 such that e1.equals(e2), and at most one null element. As implied
by its name, this interface models the mathematical set abstraction.
If you want to store sets of int values, you can use this Tuple class I wrote a while ago for another question on SO.
Set<Tuple> myTuples = new HashSet<Tuple>();
Tuple<Integer> x = Tuple.create(1, 2, 3);
Tuple<Integer> y = Tuple.create(1, 2, 3);
myTuples.add(x);
System.out.println("Set contains y: " + myTuples.contains(y)); // prints true
If order matters, you can use a SortedSet.
LinkedList uses equals to implement contains, so this should work:
public static void main(String args[]) {
static class Ints {
int[] array;
public Ints(int[] array) {
this.array = array;
}
public boolean equals(Object other) {
if (other instanceof Ints) {
return arraysEqual((Ints) other);
}
}
public boolean arraysEqual(Ints other) {
// check that this.array and other.array are same length and
// have same values. Do a null check somewhere too. :)
}
}
Ints x = new Ints(new int[] {1, 2, 3});
Ints y = new Ints(new int[] {1, 2, 3});
LinkedList<Ints> list = new LinkedList<int[]>();
list.add(x);
System.out.println("List contains y: " + list.contains(y));
}
You would probably want to extend LinkedList into your own custom data structure and define a custom equality method if you wanted anything outside of the standard checking that is in place.
If you could use a Set instead of an array it might be easier. Have a look here or here