Anything wrong about my Intset Class? - java

I design new IntSet Class that use ArrayList. first, i extends Intset by ArrayList and i start implement method. i face some problem in my union() method. here is my code...
public class IntSet extends ArrayList<Integer>{
private static final long serialVersionUID = 1L;
private ArrayList<Integer> intset;
public IntSet(){
this.intset = new ArrayList<Integer>();
}
public IntSet(ArrayList<Integer> intset){
this.intset = intset;
}
public void insert(int x){
this.intset.add(x);
}
#Override
public Integer remove(int x){
int index = intset.indexOf(x);
this.intset.remove(index);
return 1;
}
#Override
public int size(){
return this.intset.size();
}
#Override
public Integer get(int index){
return this.intset.get(index);
}
public boolean member(int x){
if(intset.indexOf(x)==-1) return false;
else return true;
}
public IntSet union(IntSet a){
IntSet intersectSet = new IntSet();
intersectSet.insert(0);
intersectSet.insert(1);
System.out.println(intersectSet.size());
System.out.println(intersectSet.contains(1));
for(int i=0; i<a.size(); i++){
}
return intersectSet;
}
public String toString(){
if(intset.size()==0) return "[]";
String s = "[" + intset.get(0).toString();
for(int i=1; i<intset.size(); i++){
s += "," + intset.get(i).toString();
}
return s += "]";
}
}
In method
union(IntSet a);
I constract new Intset object then add 2 value (0, 1) into intersectSet variable.
intersectSet.insert(0);
intersectSet.insert(1);
then i print size of intersectSet it shown me 2 that is correct!
but when i need to check that there is 1 in intersectSet or not? it shown me false.
System.out.println(intersectSet.contains(1));
In fact it should show me true because in intersectSet have integer 1.
anything wrong about my code and should i extends ArrayList for IntSet class?

Some suggestions on the class design:
Don't have your class extend ArrayList. A "set" really shouldn't be extending List. However, you should probably implement Set. This will have the added bonus of the compiler telling you what methods you need to implement for a set.....
For fastest performance (but more work!), you may want to use an internal array rather than an ArrayList.
Consider making the structure immutable, with functions that return a new copy rather than mutating the set in place. Depending on your usage, this may be a better solution, especially if you are mostly dealing with small, non-changing sets.
Again depending on your usage, you may want to override hashCode and equals to implement value based equality
When you construct the Intset with an ArrayList, you should ideally defensively copy (clone) the ArrayList. You don't want you set to change if someone mutates the original ArrayList.

The problem here is that you actually have 2 ArrayLists. The IntSet class IS A ArrayList, but this class contains a second ArrayList intset. Get rid of one of these ArrayLists. To demonstrate this add this second line:
System.out.println(intersectSet.contains(1));
System.out.println(intersectSet.intset.contains(1));
this will output:
false
true
So you are going to have to make a choice, do I inherit from ArrayList or do I contain an ArrayList. Of course what I am getting at here is Item 16 from Effective Java, Favor composition over inheritance.

You are both extending ArrayList and managing your own internal ArrayList object, this means that for all the methods which you have overridden you are interacting with your intset member variable, otherwise you are interacting with the inherited internal representation used by the ArrayList superclass. If you override the contains method you will get the correct behaviour.
I suggest that you drop the subclassing of ArrayList and instead implement the List or Set interfaces, although this depends on the exact problem you've been asked to solve.

you need to override contains method.
public boolean contains(Object o) {
return intset.contains(o);
}
and the rest of ArrayList methods that related to its elements.
and i doesn't seems to me a good solution. you may try better approach.

Related

TreeSet replacing old values by New values

I am trying to insert multiple objects in a TreeSet . The problem is one object inserts fine, but when I insert second object and tries to view both objects, I get the second object twice. How can I prevent my old values from getting replaced..
This is my POJO
public Class Question implements Comparable<Question>
{
.....
public int compareTo(Question q) {
if(vote>q.vote)
return -1;
else
return 1;
}
And this is the function which inserts object into the treeSet
public void save(String ques, String sessionId, Question question)
{
question.setQuesId(++quesId);
question.setQues(ques);
question.setSessionId(sessionId);
question.setVote(0);
setDemo.add(Question);
}
Note: "setDemo" is my treeSet object
Any advices are appreciated.
Thankyou
First of all, your comparator should handle the case in which the votes are equal.
public int compareTo(Question q) {
if(vote>q.vote) {
return -1;
} else if (vote<q.vote){
return 1;
} else {
return 0;
}
}
Secondly, make sure you override equals properly in Question.
If both the compareTo method returns 0 and the equals returns true, TreeSet will override your value, since it will detect the two values as duplicates. Otherwise, you should not get any replacements.
Although TreeSet does not use hashCode internally, I would suggest overriding that as well, since you might want to change the implementation from TreeSet to HashSet in the future.

How to create an equals method that compares two object arrays of a class?

I am trying to create a equals method that compares two objects. The thing is, I'm a bit a of new to this stuff so I'll try to explain my goal as easy as possible.
public class A {
...
}
public class B {
private A[] arr = new A[10];
public boolean equals(A[] temp) {
//compare
}
}
Assume the code above is a summary of what I have. Now, assume I had: arr.equals(Obj)
Obj being another A[] object. Now in my equals statement, I want to reference the original arr array, how do I go about doing that?
For example, let's say I wanted to compare arr's length to temp's length (aka Obj's length), how would I do that? I know it would be something like (temp.length == arr.length) but how do I access arr when I pass it through by doing arr.equals(obj)?
EDIT: Just to clarify, assume the objects aren't simple arrays. So for instance, class A could have a Name, a Type (Both Strings) and possibly a Quantity (an int), so I wouldn't be able to simply compare them like they're two normal arrays.
Thanks!
You can use java.util.Arrays.equals(Object[] a, Object[] a2) which tests if the two specified arrays of Objects are equal to one another
Use the keyword this, which always represents the object you are applying the method to (immediately before the dot). For example:
public boolean equals(A[] temp) {
return this.length == temp.length ;
}
Now, in the particular case of your code, you are not defining method equals as part of class A, but of a class B whose instances contain arr. Then, the solution would be:
public boolean equals(A[] temp) {
return this.arr.length == temp.length ;
}
Write a equals mwthod in your class A
public class A {
...
//Override equals method.
}
Now if you want to compare 2 arrays of class A you can simply use java.utils.Arrays.equals(A a1[], A a2[]);
You have to override equals method in class A coz java.utils.Arrays.equals internally uses class A's equals.
Here is an example, go through it.

ArrayList Generic Sorter

I want to pass in an arraylist and sort it no matter whats in it
Error I am getting: Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Character
ArrayList myArray = new ArrayList();
myArray.add("wayne");
myArray.add("bob");
myArray.add('h');
myArray.add(4);
myArray.add(5.50);
ArrayList sortedArray = Validate.Sort(myArray);
for(Object x: sortedArray)
{
System.out.println(x);
}
public static ArrayList Sort(ArrayList value)
{
Collections.sort(value);
return value;
}
Your ArrayList has a mix of String and char values. So when the two try to get compared, the String's compareTo method is being called. It has a signature of compareTo(String,String), so it's trying to cast the char to a String. Either put all Strings in, or write a custom comparator that handles mixed types like this.
Take a look at Comparator:
http://docs.oracle.com/javase/6/docs/api/java/util/Comparator.html
In your case the compareTo() may look like:
public int compareTo(Object a, Object b){
if(a == b)
return 0;
if(a==null)
return 1;
if(b==null)
return -1;
return a.toString().compareTo(b.toString);
}
But I think this would be kind of useless.
I want to pass in an arraylist and sort it no matter whats in it
What is this supposed to mean? A total ordering is a binary relation which satisfies some properties (antisimmetry, transitivity, totality). More easily, given two elements, you must identify a criterion to determine which is smaller/bigger than the other.
You cannot do this, unless you know what these elements actually are. If you want to sort an array of whatever, given object A and B, whose types you don't even know, how can you tell which is bigger than the other?
In Java, you might use the hashCode, which is indeed a criterion, but it's hardly useful. If you want to avoid duplicates, you can use a Set rather than a List. Anyway, if you really want to sort elements based on their hashCode, you can do it like this:
private static final Comparator<Object> hashComparator
= new Comparator<Object>() {
#Override
public int compare(Object a, Object b) {
return System.identityHashCode(a) - System.identityHashCode(b);
}
#Override
public boolean equals(Object obj) {
//this is a static singleton, nothing can be equal to it
return false;
}
};
public static ArrayList Sort(ArrayList value)
{
Collections.sort(value, hashComparator);
return value;
}
EDIT: if you are interested in sorting a list of just Strings and Characters (or if you want to sort items based on their string representation) the right thing to do is probably convert everything to strings, or use a SortedMap<String, Object>. Otherwise, you can do the same I just showed you before, but using a more specific compare function, such as:
public int compare(Object a, Object b) {
return a.toString().compareTo(b.toString());
}

Not sure how to sort an ArrayList based on parts of Objects in that ArrayList (Java)

I have a Sorts class that sorts (based on insertion sort, which was the assignment's direction) any ArrayList of any type passed through it, and uses insertion sort to sort the items in the list lexicographically:
public class Sorts
{
public static void sort(ArrayList objects)
{
for (int i=1; i<objects.size(); i++)
{
Comparable key = (Comparable)objects.get(i);
int position = i;
while (position>0 && (((Comparable)objects.get(position)).compareTo(objects.get(position-1)) < 0))
{
objects.set(position, objects.get(position-1));
position--;
}
objects.set(position, key);
}
}
}
In one of my other files, I use a method (that is called in main later) that sorts objects of type Owner, and we have to sort them by last name (if they are the same, then first name):
Directions: "Sort the list of owners by last name from A to Z. If more than one owner have the same last name, compare their first names. This method calls the sort method defined in the Sorts class."
What I thought first was to get the last name of each owner in a for loop, add it to a temporary ArrayList of type string, call Sorts.sort(), and then re-add it back into the ArrayList ownerList:
public void sortOwners() {
ArrayList<String> temp = new ArrayList<String>();
for (int i=0; i<ownerList.size(); i++)
temp.add(((Owner)ownerList.get(i)).getLastName());
Sorts.sort(temp);
for (int i=0; i<temp.size(); i++)
ownerList.get(i).setLastName(temp.get(i));
}
I guess this was the wrong way to approach it, as it is not sorting when I compile.
What I now think I should do is create two ArrayLists (one is firstName, one is LastName) and say that, in a for loop, that if (lastName is the same) then compare firstName, but I'm not sure if I would need two ArrayLists for that, as it seems needlessly complicated.
So what do you think?
Edit: I am adding a version of compareTo(Object other):
public int compareTo(Object other)
{
int result = 0;
if (lastName.compareTo(((Owner)other).getLastName()) < 0)
result = -1;
else if (lastName.compareTo(((Owner)other).getLastName()) > 0)
result = 1;
else if (lastName.equals(((Owner)other).getLastName()))
{
if (firstName.compareTo(((Owner)other).getFirstName()) < 0)
result = -1;
else if (firstName.compareTo(((Owner)other).getFirstName()) > 0)
result = 1;
else if (firstName.equals(((Owner)other).getFirstName()))
result = 0;
}
return result;
}
I think the object should implement a compareTo method that follows the normal Comparable contract--search for sorting on multiple fields. You are correct that having two lists is unnecessary.
If you have control over the Owner code to begin with, then change the code so that it implements Comparable. Its compareTo() method performs the lastName / firstName test described in the assignment. Your sortOwners() method will pass a List<Owner> directly to Sorts.sort().
If you don't have control over Owner, then create a subclass of Owner that implements Comparable. Call it OwnerSortable or the like. It accepts a regular Owner object in its constructor and simply delegates all methods other than compareTo() to the wrapped object. Its compareTo() will function as above. Your sortOwners() method will create a new List<OwnerSortable> out of the Owner list. It can then pass this on to Sorts.sort().
Since you have an ArrayList of objects, ordinarily we would use the Collections.sort() method to accomplish this task. Note the method signature:
public static <T extends Comparable<? super T>> void sort(List<T> list)
What's important here is that all the objects being sorted must implement the Comparable interface, which allows objects to be compared to another in numerical fashion. To clarify, a Comparable object has a method called compareTo with the following signature:
int compareTo(T o)
Now we're getting to the good part. When an object is Comparable, it can be compared numerically to another object. Let's look at a sample call.
String a = "bananas";
String b = "zebras";
System.out.println(a.compareTo(b));
The result will be -24. Semantically, since zebras is farther in the back of the dictionary compared to bananas, we say that bananas is comparatively less than zebras (not as far in the dictionary).
So the solution should be clear now. Use compareTo to compare your objects in such a way that they are sorted alphabetically. Since I've shown you how to compare strings, you should hopefully have a general idea of what needs to be written.
Once you have numerical comparisons, you would use the Collections class to sort your list. But since you have your own sorting ability, not having access to it is no great loss. You can still compare numerically, which was the goal all along! So this should make the necessary steps clearer, now that I have laid them out.
Since this is homework, here's some hints:
Assuming that the aim is to implement a sort algorithm yourself, you will find that it is much easier (and more performant) to extract the list elements into an array, sort the array and then rebuild the list (or create a new one).
If that's not the aim, then look at the Collections class.
Implement a custom Comparator, or change the object class to implement Comparable.

Changing semantics of subclass methods in java

I've recently learned like 3 new languages and I'm starting to get them confused. I haven't worked Java in doing anything particularly complex (outside of android) in a couple years. I'm having trouble remembering if this is possible:
I'm subclassing ArrayList mainly so I can keep the arraylist ordered. I'm trying to override the add(object) method but I want it to return an int instead of a boolean (the location of the object that was added). But I'm getting errors on the return type of my method.
Is what I want even possible in the language? Can you have a method in a subclass return something different than the superclass' method?
Or am I trying to do something stupid? Is this breaking the is-a idea of inheritance? Should I just encapsulation an arraylist instead of extending it?
For reference, a portion of what I'm trying to do:
public class AuthorArray extends ArrayList \{
#Override
public int add(Author object) {
super.add(object);
Collections.sort(this, new SortByLastName());
return this.indexOf(object);
}
}
Can you have a method in a subclass return something different than the superclass' method?
In general, no. The only exception is covariant return types, when an overridden method returns a subclass of the return type in the base class/interface method. This became possible with Java5, and is good practice. But your case does not fall into this category.
Is this breaking the is-a idea of inheritance?
Yes. Users of ArrayList expect to get a boolean return value from add, and see the elements in the same order they added them, and you would break that expectation. Don't do that.
Should I just encapsulation an arraylist instead of extending it?
Yes. Then you can define your own interface, with whatever contract you prefer. But first, consider using a TreeSet instead.
Changing semantics is bad. In your case, changing method name from add to myadd would fix your problem, if you want a simple fix.
Personally i would recommend learning how to use Google guava-libraries immutable, sorted data structures with 'function', to get a refresher overview, browse youtube.
But here in standard Java, I made example, how to use TreeSet autosort - custom class, 2 value comparator, and efficient binary search equivalent.
public static class customC {
private String name;
private int value;
public customC(String name, int value) {super();this.name = name;this.value = value;}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public int getValue() {return value;}
public void setValue(int value) {this.value = value;}
#Override
public String toString() {
return new StringBuilder().append("[").append(this.name)
.append(":").append(this.value).append("]").toString();
}
}
public static void main(String[] args) {
TreeSet<customC> ts = new TreeSet<customC>(new Comparator<customC>(){
public int compare(customC a, customC b) {
int result = a.getName().compareToIgnoreCase(b.getName());
return (result != 0 ? result : a.getValue() - b.getValue());
}
});
ts.add(new customC("ab", 1988));
ts.add(new customC("ab", 1979));
ts.add(new customC("ba", 1988));
ts.add(new customC("ab", 1984));
ts.add(new customC("ab", 1980));
customC ce = new customC("ab", 1983);
ts.add(ce);
StringBuilder sb = new StringBuilder();
sb.append(ts.headSet(ce).last()).append(" comes before ")
.append(ce).append("\n").append(ts);
System.out.println(sb.toString());
}
This will output:
[ab:1980] comes before [ab:1983]
[[ab:1979], [ab:1980], [ab:1983], [ab:1984], [ab:1988], [ba:1988]]
The List interface guarantees that elements will be returned in the same order that they are added. Thus if you only have one thread manipulating the list you can easily perform an add and then request its size. size - 1 is the ordinal value of the element.
If the above order is not what you want then you have two choices - either sort the list using Collection.sort() methods, or use a SortedSet. Both methods can take on a comparator.
I've never found the need to extend the Java collections framework and do not recommend that you do so in this circumstance.

Categories