import java.util.*;
public class test4 {
public static void main(String[] args){
PriorityQueue[] P = new PriorityQueue[10];
P[1] = new PriorityQueue<ClassEntry>();
P[1].add(new ClassEntry(1.2,1));
P[1].add(new ClassEntry(1.5,2));
P[1].add(new ClassEntry(1.2,3));
P[1].add(new ClassEntry(10,4));
P[1].remove(new ClassEntry(10,4));//I can't delete this object???
System.out.println(P[1].size());
ClassEntry ce = (ClassEntry) P[1].peek();
System.out.println(P[1].size());
System.out.println(ce.sim+"\t"+ce.index);
}
}
Why i can't delete (10,4)? Can somebody teach how to implement...thanks!
ClassEntry has to override and implement Object.equals(Object o) for remove to work. For example:
class ClassEntry{
float a;
int b;
public ClassEntry(float a, int b){
//...
}
#Override
public boolean equals(Object o){
if(o instanceof ClassEntry){
ClassEntry c = (ClassEntry)o;
return a == c.a && b == c.b;
}
return false;
}
}
EDIT: As was kindly pointed out by #Jim Garrison, if you do not implement equals the default behaviour, which is to compare objects by reference, is used. In this case for your code to work you will need to remove like this:
PriorityQueue[] P = new PriorityQueue[10];
P[1] = new PriorityQueue<ClassEntry>();
ClassEntry entry = new ClassEntry(10,4);
P[1].add(entry);
//remove object with the same reference as the added one
P[1].remove(entry);
Related
Below is my code (can be copy paste in https://www.compilejava.net/ with -ea as command line option).
I have an Object called Main. I have Main inside a List. If 2 properties (a and b) are equal to another Main object in the list, property strings should be concatenated. Furthermore, duplicates (when the 2 properties are equal) should than be removed (so the list can not contain 2 or more Mains in which both a and b are the same).
I tried it with a HashMap, hashCode, but I can not figure it out well. Note: I use OpenJDK-12 and can not use newer versions.
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class Main {
final int a;
final int b;
final List<String> strings;
Main(int a, int b, List<String> strings) {
this.a = a;
this.b = b;
this.strings = strings;
}
private static Main generateMain0() {
return new Main(0, 1, createListWithOneElement("merge me with main1"));
}
public static void main(String[] args) {
Main main0 = generateMain0();
Main main1 = new Main(0, 1, createListWithOneElement("merge me with main2"));
Main main2 = new Main(0, 2, createListWithOneElement("leave me alone"));
Main main3 = new Main(0, 2, createListWithOneElement("leave me alone also"));
List<Main> mains = new ArrayList<>();
mains.add(main0);
mains.add(main1);
mains.add(main2);
mains.add(main3);
// Do magic here to remove duplicate and concat property strings
// main1 should be removed, since property a and b were equal to main0 property a and b
assert mains.size() == 3;
Main main0Copy = generateMain0();
main0Copy.strings.add("merge me with main2");
// The first element should be main0. It should also contain
// the strings of main1 since property a and b were equal
assert mains.get(0).equals(main0Copy);
assert mains.get(1).equals(main2);
assert mains.get(2).equals(main3);
}
private static List<String> createListWithOneElement(String value) {
List<String> l = new ArrayList<>();
l.add(value);
return l;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Main main = (Main) o;
return a == main.a &&
b == main.b &&
strings.equals(main.strings);
}
#Override
public int hashCode() {
return Objects.hash(a, b, strings);
}
}
If, as you said in the comments, you can use a fully custom List, you can try the code below.
Internally, it uses a combination of a List and a Map to find out if a combination of a and b was already added to the "List". If yes, it adds all strings of the given Main to the existing Main. If not, it adds the given Main the the list.
package example;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MainList {
private final List<Main> mains;
private final Map<Key, Main> lookup;
public MainList() {
this.mains = new ArrayList<>();
this.lookup = new HashMap<>();
}
public Main get(int index) {
return this.mains.get(index);
}
public void add(Main main) {
final Key key = new Key(main.a, main.b);
Main existingMain = this.lookup.get(key);
if (existingMain == null) {
this.mains.add(main);
this.lookup.put(key, main);
} else {
existingMain.strings.addAll(main.strings);
}
}
public void remove(Main main) {
final Key key = new Key(main.a, main.b);
Main existingMain = this.lookup.get(key);
if (existingMain != null) {
if (existingMain.equals(main)) {
this.mains.remove(existingMain);
this.lookup.remove(key);
} else {
existingMain.strings.removeAll(main.strings);
}
}
}
public void remove(int index) {
final Main removedMain = this.mains.remove(index);
final Key key = new Key(removedMain.a, removedMain.b);
this.lookup.remove(key);
}
public int size() {
return this.mains.size();
}
private static class Key {
private final int a;
private final int b;
private Key(int a, int b) {
this.a = a;
this.b = b;
}
#Override
public boolean equals(Object object) {
if (this == object) {
return true;
} else if (object == null || getClass() != object.getClass()) {
return false;
}
Key key = (Key) object;
return this.a == key.a && this.b == key.b;
}
#Override
public int hashCode() {
return 31 * this.a + 31 * this.b;
}
}
}
I've been trying to find possible answers, but found none.
I've got an ArrayList full of custom objects. One of their fields is a boolean.
I want to put this object first, keeping the rest of elements
For instance, if I've got this list and obj5 is the one with this boolean set to true:
obj3, obj2, obj5, obj7, obj9
I'd like to get this:
obj5, obj3, obj2, obj7, obj9
EDIT: CAN'T USE LAMBDAS, JAVA 6
EDIT 2: PLEASE NOTE THAT THE REST OF THE LIST MUST KEEP THE OLD ORDER
EDIT 3: In short words, I need this program to output [B, A, C, D, E]:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Trip {
#Override
public String toString() {
return name;
}
private String name;
private boolean freeCancellation;
public Trip(String name, boolean freeCancellation) {
this.name = name;
this.freeCancellation = freeCancellation;
}
static Comparator<Trip> myOrder = new Comparator<Trip>() {
public int compare(Trip a, Trip b) {
if (a.freeCancellation == b.freeCancellation) return 0;
return a.freeCancellation ? -1 : 1;
}
};
public static void main(String [] args){
Trip t1 = new Trip("A", false);
Trip t2 = new Trip("B", true);
Trip t3 = new Trip("C", false);
Trip t4 = new Trip("D", true);
Trip t5 = new Trip("E", false);
List<Trip> tripList = new ArrayList<>();
tripList.add(t1);
tripList.add(t2);
tripList.add(t3);
tripList.add(t4);
tripList.add(t5);
System.out.println(Arrays.toString(tripList.toArray()));
Collections.sort(tripList, myOrder);
//result should be [B, A, C, D, E]
System.out.println(Arrays.toString(tripList.toArray()));
}
}
Write a Comparator.
Comparator<MyType> myOrder = new Comparator<MyType>() {
public int compare(MyType a, MyType b) {
return (b.booleanField() ? 1 : 0) - (a.booleanField() ? 1 : 0);
}
}
Sort using this comparator.
Collections.sort(myList, myOrder);
See Collections.sort
Edit
So it seems that what you're actually asking for is to move just one matching element to the front of your list. That ought to be pretty easy.
Find the index of the element you want to move:
int foundIndex = -1;
for (int i = 0; i < tripList.size(); ++i) {
if (tripList.get(i).freeCancellation) {
foundIndex = i;
break;
}
}
If you find such an element, and it is not already at the start, move it to the start:
if (foundIndex > 0) {
tripList.add(0, tripList.remove(foundIndex));
}
List<Object> objList = findObj(name);Collections.sort(objList, new Comparator<Object>() {
#Override
public int compare(Object a1, Object a2) {
return (a1.getBooleanField()== a2.getBooleanField())?0:(a1.getBooleanField()?1:-1);
}});
This might help you to resolve this. You modify the results by changing the compare logic
Here is an example of how to achieve this:
class Element {
public boolean shouldBeFirst();
}
List<Element> elements;
elements.sort(Comparator.comparing(Element::shouldBeFirst));
This works because the natural ordering of booleans is true first.
If you can't use Java 8 then the equivalent would be something like:
Collections.sort(elements, new Comparator() {
int compareTo(Element el1, Element el2) {
return (el1.shouldBeFirst() ? 1 : 0) - (el2.shouldBeFirst() ? 1 : 0);
}
}
import java.util.*;
public class Test {
public static void main(String[] args) {
List<A> list = new ArrayList<A>();
list.add(new A(true));
list.add(new A(false));
list.add(new A(true));
list.add(new A(false));
Collections.sort(list);
System.out.println(list);
}
}
class A implements Comparable<A> {
private boolean b;
public A(boolean b) {
this.b = b;
}
public boolean isB() {
return b;
}
public void setB(boolean b) {
this.b = b;
}
#Override
public int compareTo(A a) {
return a.isB() ? 1 : -1;
}
#Override
public String toString() {
return "A [b=" + b + "]";
}
}
Maybe this is what you are looking for.
This is solution if you want to give natural ordering to object, then implement Comparable and use Collections.sort - https://docs.oracle.com/javase/6/docs/api/java/util/Collections.html#sort(java.util.List).
If you have various members inside class, then maybe go with Comparator implementation, that way you can achieve many ways of sorting your objects based on different members.
If I understood what are you asking ,you need to create a new class called "Comparators".
in this class you need to define your methods and they need to be static final ...
then you can use it by calling to Collections.sort(-your array-, Comparator method name);
I am trying to find how many time one string occurs in an ArrayList. I managed to find by using Collections.frequency(list,object);
public class Main {
public static void main(String[] args) {
ArrayList<Main> d = new ArrayList<Main>();
Main m = new Main();
m.setA("a");
d.add(m);
Main m11 = new Main();
m11.setA("a");
d.add(m11);
Main m111 = new Main();
m111.setA("a");
d.add(m111);
int c = Collections.frequency(d, m11);
System.out.println(c);
}
private String a,b,c;
public String getA() {
return a;
}
public void setA(String a) {
this.a = a;
}
public String getB() {
return b;
}
public void setB(String b) {
this.b = b;
}
public String getC() {
return c;
}
public void setC(String c) {
this.c = c;
}
#Override
public boolean equals(Object o) {
return a.equals(((Main)o).a);
}
}
In the above code I manage to find occurrences of a. But how can I find other stuff also, like if I want to find occurrences of b and calso? Is there a way I can do it? Can I have many equals function?
Implementation of frequency.
public static int frequency(Collection<?> c, Object o) {
int result = 0;
if (o == null) {
for (Object e : c)
if (e == null)
result++;
} else {
for (Object e : c)
if (o.equals(e))
result++;
}
return result;
}
So this works on equals method and you can't have more than one equals.
You have to manually iterate over the list and find the frequency for different properties.
ArrayList<Main> d = new ArrayList<Main>();
int counter = 0;
foreach( var item in d )
{
if( item = "The string you desire" )
{
counter += 1;
}
}
// This is the total count of the string you wanted in the collection
console.write(counter);
If you want to make this a generic function, it would just take 2 parameters, the collection, and the item you desire.
I want to apply the inteserction ( using this method http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/Sets.html) to sets that contain objects not primitive. I wrote this code but I have that the intersection is empty..
Concept a = new Concept("Dog");
Concept b = new Concept("Tree");
Concept c= new Concept("Dog");
HashSet<Concept> set_1 = new HashSet<Concept>();
HashSet<Concept> set_2 = new HashSet<Concept>();
set_1.add(a);
set_1.add(b);
set_1.add(c);
SetView<Concept> inter = Sets.intersection(set_1,set_2);
System.out.println(inter.size()); ----> I HAVE ZERO !!!
The Concept class contains only a private member of type String and the method of get and set ..I don't have equals() and hashCode().
This works as expected (notice equals and hashCode on Concept)
package com.stackoverflow.so19634761;
import com.google.common.collect.Sets;
import com.google.common.collect.Sets.SetView;
import java.util.Set;
public class ISect {
public static void main(final String[] args) {
final Concept a = new Concept("Dog");
final Concept b = new Concept("Tree");
final Concept c= new Concept("Dog");
final Set<Concept> set1 = Sets.newHashSet(a);
final Set<Concept> set2 = Sets.newHashSet(b, c);
final SetView<Concept> inter = Sets.intersection(set1, set2);
System.out.println(inter); // => [Concept [data=Dog]]
}
private static class Concept {
private final String data;
// below this point code was generated by eclipse.
public String getData() {
return data;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((data == null) ? 0 : data.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;
Concept other = (Concept) obj;
if (data == null) {
if (other.data != null)
return false;
} else if (!data.equals(other.data))
return false;
return true;
}
public Concept(String data) {
this.data = data;
}
#Override
public String toString() {
return "Concept [data=" + data + "]";
}
}
}
You are putting Concept inside Sets, not the Strings - Dog, Tree. U also need to override the hashcode and equals of the concept class for it to work
At first, You need to override equals and hashcode method on Concept class. You don't need third party library. Just use
set_1.retainAll(set2);
set_1.retainAll(set2) transforms set_1 into the intersection of set_1 and set_2. (The intersection of two sets is the set containing only the elements common to both sets.).
I'd like my EqualTester generic class to call the overridden equals(...) method of its generic parameter, but it seems to call Object.equals instead. Here is my test code:
import junit.framework.TestCase;
public class EqualityInsideGenerics extends TestCase {
public static class EqualTester<V> {
public boolean check(V v1, V v2) {
return v1.equals(v2);
}
}
public static class K {
private int i;
private Object o;
public K(Object o, int i) {
this.o = o;
this.i = i;
}
public boolean equals(K k) {
return ((k.o != null && k.o.equals(o)) || o == null) && (k.i == i);
}
};
public void testEqual() {
K k1 = new K(null, 0);
K k2 = new K(null, 0);
assertTrue(k1.equals(k2)); // This one ok
EqualTester<K> tester = new EqualTester<K>();
assertTrue(tester.check(k1, k2)); // This one KO!
}
}
Could you please explain why this does not work, and how I could change my EqualTester class?
Is it because K does not actually override the Object.equals() method (because the parameter does not have the correct type)?
Thanks.
You need to code as public boolean equals(Object k), and then cast to k.
Right now you are just overloading the equals method.
It's also useful to add #Override annotation to the method.
When overriding the method signature must match exactly.
Because equals(K k) does not actually override the equals(Object o) method.
You must override equals(Object o) exactly in order for it to work.
Thanks Padmarag and Phill!
A solution that works:
#Override
public boolean equals(Object obj) {
if (!(obj instanceof K)) {
return false;
}
K k = (K)obj;
return ((k.o != null && k.o.equals(o)) || o == null) && (k.i == i);
}
Comments welcome: I started programming in Java only a few days ago...