Changing semantics of subclass methods in java - 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.

Related

Checking for duplicated data in Java array list [duplicate]

I want to check whether a List contains an object that has a field with a certain value. Now, I could use a loop to go through and check, but I was curious if there was anything more code efficient.
Something like;
if(list.contains(new Object().setName("John"))){
//Do some stuff
}
I know the above code doesn't do anything, it's just to demonstrate roughly what I am trying to achieve.
Also, just to clarify, the reason I don't want to use a simple loop is because this code will currently go inside a loop that is inside a loop which is inside a loop. For readability I don't want to keep adding loops to these loops. So I wondered if there were any simple(ish) alternatives.
Streams
If you are using Java 8, perhaps you could try something like this:
public boolean containsName(final List<MyObject> list, final String name){
return list.stream().filter(o -> o.getName().equals(name)).findFirst().isPresent();
}
Or alternatively, you could try something like this:
public boolean containsName(final List<MyObject> list, final String name){
return list.stream().map(MyObject::getName).filter(name::equals).findFirst().isPresent();
}
This method will return true if the List<MyObject> contains a MyObject with the name name. If you want to perform an operation on each of the MyObjects that getName().equals(name), then you could try something like this:
public void perform(final List<MyObject> list, final String name){
list.stream().filter(o -> o.getName().equals(name)).forEach(
o -> {
//...
}
);
}
Where o represents a MyObject instance.
Alternatively, as the comments suggest (Thanks MK10), you could use the Stream#anyMatch method:
public boolean containsName(final List<MyObject> list, final String name){
return list.stream().anyMatch(o -> name.equals(o.getName()));
}
You have two choices.
1. The first choice, which is preferable, is to override the `equals()` method in your Object class.
Let's say, for example, you have this Object class:
public class MyObject {
private String name;
private String location;
//getters and setters
}
Now let's say you only care about the MyObject's name, that it should be unique so if two `MyObject`s have the same name they should be considered equal. In that case, you would want to override the `equals()` method (and also the `hashcode()` method) so that it compares the names to determine equality.
Once you've done this, you can check to see if a Collection contains a MyObject with the name "foo" by like so:
MyObject object = new MyObject();
object.setName("foo");
collection.contains(object);
However, this might not be an option for you if:
You are using both the name and location to check for equality, but you only want to check if a Collection has any `MyObject`s with a certain location. In this case, you've already overridden `equals()`.
`MyObject` is part of an API that you don't have liberty to change.
If either of these are the case, you'll want option 2:
2. Write your own utility method:
public static boolean containsLocation(Collection<MyObject> c, String location) {
for(MyObject o : c) {
if(o != null && o.getLocation.equals(location)) {
return true;
}
}
return false;
}
Alternatively, you could extend ArrayList (or some other collection) and then add your own method to it:
public boolean containsLocation(String location) {
for(MyObject o : this) {
if(o != null && o.getLocation.equals(location)) {
return true;
}
}
return false;
}
Unfortunately there's not a better way around it.
This is how to do it using Java 8+ :
boolean isJohnAlive = list.stream().anyMatch(o -> "John".equals(o.getName());
Google Guava
If you're using Guava, you can take a functional approach and do the following
FluentIterable.from(list).find(new Predicate<MyObject>() {
public boolean apply(MyObject input) {
return "John".equals(input.getName());
}
}).Any();
which looks a little verbose. However the predicate is an object and you can provide different variants for different searches. Note how the library itself separates the iteration of the collection and the function you wish to apply. You don't have to override equals() for a particular behaviour.
As noted below, the java.util.Stream framework built into Java 8 and later provides something similar.
Collection.contains() is implemented by calling equals() on each object until one returns true.
So one way to implement this is to override equals() but of course, you can only have one equals.
Frameworks like Guava therefore use predicates for this. With Iterables.find(list, predicate), you can search for arbitrary fields by putting the test into the predicate.
Other languages built on top of the VM have this built in. In Groovy, for example, you simply write:
def result = list.find{ it.name == 'John' }
Java 8 made all our lives easier, too:
List<Foo> result = list.stream()
.filter(it -> "John".equals(it.getName())
.collect(Collectors.toList());
If you care about things like this, I suggest the book "Beyond Java". It contains many examples for the numerous shortcomings of Java and how other languages do better.
Binary Search
You can use Collections.binarySearch to search an element in your list (assuming the list is sorted):
Collections.binarySearch(list, new YourObject("a1", "b",
"c"), new Comparator<YourObject>() {
#Override
public int compare(YourObject o1, YourObject o2) {
return o1.getName().compareTo(o2.getName());
}
});
which will return a negative number if the object is not present in the collection or else it will return the index of the object. With this you can search for objects with different searching strategies.
Map
You could create a Hashmap<String, Object> using one of the values as a key, and then seeing if yourHashMap.keySet().contains(yourValue) returns true.
Eclipse Collections
If you're using Eclipse Collections, you can use the anySatisfy() method. Either adapt your List in a ListAdapter or change your List into a ListIterable if possible.
ListIterable<MyObject> list = ...;
boolean result =
list.anySatisfy(myObject -> myObject.getName().equals("John"));
If you'll do operations like this frequently, it's better to extract a method which answers whether the type has the attribute.
public class MyObject
{
private final String name;
public MyObject(String name)
{
this.name = name;
}
public boolean named(String name)
{
return Objects.equals(this.name, name);
}
}
You can use the alternate form anySatisfyWith() together with a method reference.
boolean result = list.anySatisfyWith(MyObject::named, "John");
If you cannot change your List into a ListIterable, here's how you'd use ListAdapter.
boolean result =
ListAdapter.adapt(list).anySatisfyWith(MyObject::named, "John");
Note: I am a committer for Eclipse ollections.
Predicate
If you dont use Java 8, or library which gives you more functionality for dealing with collections, you could implement something which can be more reusable than your solution.
interface Predicate<T>{
boolean contains(T item);
}
static class CollectionUtil{
public static <T> T find(final Collection<T> collection,final Predicate<T> predicate){
for (T item : collection){
if (predicate.contains(item)){
return item;
}
}
return null;
}
// and many more methods to deal with collection
}
i'm using something like that, i have predicate interface, and i'm passing it implementation to my util class.
What is advantage of doing this in my way? you have one method which deals with searching in any type collection. and you dont have to create separate methods if you want to search by different field. alll what you need to do is provide different predicate which can be destroyed as soon as it no longer usefull/
if you want to use it, all what you need to do is call method and define tyour predicate
CollectionUtil.find(list, new Predicate<MyObject>{
public boolean contains(T item){
return "John".equals(item.getName());
}
});
Here is a solution using Guava
private boolean checkUserListContainName(List<User> userList, final String targetName){
return FluentIterable.from(userList).anyMatch(new Predicate<User>() {
#Override
public boolean apply(#Nullable User input) {
return input.getName().equals(targetName);
}
});
}
contains method uses equals internally. So you need to override the equals method for your class as per your need.
Btw this does not look syntatically correct:
new Object().setName("John")
If you need to perform this List.contains(Object with field value equal to x) repeatedly, a simple and efficient workaround would be:
List<field obj type> fieldOfInterestValues = new ArrayList<field obj type>;
for(Object obj : List) {
fieldOfInterestValues.add(obj.getFieldOfInterest());
}
Then the List.contains(Object with field value equal to x) would be have the same result as fieldOfInterestValues.contains(x);
Despite JAVA 8 SDK there is a lot of collection tools libraries can help you to work with, for instance:
http://commons.apache.org/proper/commons-collections/
Predicate condition = new Predicate() {
boolean evaluate(Object obj) {
return ((Sample)obj).myField.equals("myVal");
}
};
List result = CollectionUtils.select( list, condition );

Which is good practice - Modifying a List in the method, or returning a new List in the method?

Example code:
modifyMyList(myList);
public void modifyMyList(List someList){
someList.add(someObject);
}
or:
List myList = modifyMyList(myList);
public List modifyMyList(List someList){
someList.add(someObject)
return someList;
}
There is also a 3rd option I believe: You can create a new List in modifyMyList method and return this new List...
( 3rd option is here, I was too lazy but someone already added it in the answers: )
List myList = modifyMyList(myList);
public List modifyMyList(List someList){
List returnList = new ArrayList();
returnList.addAll(someList);
returnList.add(someObject);
return Collections.unmodifiableList(returnList);
}
Is there any reason why I should choose one over another? What should be considered in such case?
I have a (self imposed) rule which is "Never mutate a method parameter in a public method". So, in a private method, it's ok to mutate a parameter (I even try to avoid this case too). But when calling a public method, the parameters should never be mutated and should be considered immutable.
I think that mutating method arguments is a bit hacky and can lead to bugs that are harder to see.
I have been known to make exceptions to this rule but I need a really good reason.
Actually there is no functional difference.
You'll come to know the difference when you want the returned list
List someNewList = someInstnace.modifyMyList(list);
The second is probably confusing as it implies a new value is being created and returned - and it isn't.
An exception would be if the method was part of a 'fluent' API, where the method was an instance method and was modifying its instance, and then returning the instance to allow method chaining: the Java StringBuilder class is an example of this.
In general, however, I wouldn't use either.
I'd go for your third option: I write a method that creates and returns a new list with the appropriate change. This is a bit artificial in the case of your example, as the example is really just reproducing List.add(), but...
/** Creates a copy of the list, with val appended. */
public static <T> List<T> modifyMyList(List<T> list, T val) {
List<T> xs = new ArrayList<T>(list);
xs.add(val);
return xs;
}
Aside: I wouldn't, as suggested by Saket return an immutable list. His argument for immutability and parallelism is valid. But most of the time Java programmers expect to be able to modify a collection, except in special circumstances. By making you method return an immutable collection, you limit it's reusability to such circumstances. (The caller can always make the list immutable if they want to: they know the returned value is a copy and won't be touched by anything else.) Put another way: Java is not Clojure. Also, if parallelism is a concern, look at Java 8 and streams (the new kind - not I/O streams).
Here's a different example:
/** Returns a copy of a list sans-nulls. */
public static <T> List<T> compact(Iterable<T> it) {
List<T> xs = new ArrayList<T>();
for(T x : it)
if(x!=null) xs.add(x);
return xs;
}
Note that I've genercized the method and made it more widely applicable to taking an Iterable instead of a list. In real code, I'd have two overloaded versions, one taking an Iterable and one an Iterator. (The first would be implemented by calling the second, with the iterable's iterator.) Also, I've made it static as there was no reason for your method to be an instance method (it does not depend on state from the instance).
Sometimes, though, if I'm writing library code, and if it is not clear whether a mutating or non-mutating implementation is more generally useful, I create both. Here's a fuller example:
/** Returns a copy of the elements from an Iterable, as a List, sans-nulls. */
public static <T> List<T> compact(Iterable<T> it) {
return compact(it.iterator());
}
public static <T> List<T> compact(Iterator<T> iter) {
List<T> xs = new ArrayList<T>();
while(iter.hasNext()) {
T x = iter.next();
if(x!=null) xs.add(x);
}
return xs;
}
/** In-place, mutating version of compact(). */
public static <T> void compactIn(Iterable<T> it) {
// Note: for a 'fluent' version of this API, have this return 'it'.
compactIn(it.iterator());
}
public static <T> void compactIn(Iterator<T> iter) {
while(iter.hasNext()) {
T x = iter.next();
if(x==null) iter.remove();
}
}
If this was in a real API I'd check the arguments for null and throw IllegalArgumentException. (NOT NullPointerException - though it is often used for this purpose. NullPointerException happens for other reasons as well, e.g. buggy code. IllegalArgumentException is better for invalid parameters.)
(There'd also be more Javadoc than actual code too!)
The first and second solution are very similar, The advantage of the second is to permit chaining. The question of "is it a good practise" is subjected to debate as we can see here:
Method Chaining in Java
So the real question is between the first solution with mutable list and the third with a unmutable list, and again, there is not a unique response, it is the same debate between returning String, which are immutable and using Stringbuffer, which are mutable but permits better performance.
If you need reliablility of your API , and if you don't have performance issues use immutable (the third solution). Use it if your lists are always small.
If you need only performance use a mutable list (the first solution)
I will recommend creating a new list in the method and returning an immutable list. That way your code will work even when you are passed in an Immutable list. It is generally a good practice to create immutable objects as we generally move towards functional programming and try to scale across multiple processor architectures.
List myList = modifyMyList(myList);
public List modifyMyList(List someList){
List returnList = new ArrayList();
returnList.addAll(someList);
returnList.add(someObject);
return Collections.unmodifiableList(returnList);
}
As I said in my other answer, I don't think you should mutate the list parameter. But there are times where you also don't want to take a copy of the original list and mutate the copy.
The original list might be large so the copy is expensive
You want the copy to be kept up-to-date with any updates to the original list.
In these scenarios, you could create a MergedList which is a view over two (or perhaps more) lists
import java.util.*;
public class MergedList<T> extends AbstractList<T> {
private final List<T> list1;
private final List<T> list2;
public MergedList(List<T> list1, List<T> list2) {
this.list1 = list1;
this.list2 = list2;
}
#Override
public Iterator<T> iterator() {
return new Iterator<T>() {
Iterator<T> it1 = list1.iterator();
Iterator<T> it2 = list1.iterator();
#Override
public boolean hasNext() {
return it1.hasNext() || it2.hasNext();
}
#Override
public T next() {
return it1.hasNext() ? it1.next() : it2.next();
}
};
}
#Override
public T get(int index) {
int size1 = list1.size();
return index < size1 ? list1.get(index) : list2.get(index - size1);
}
#Override
public int size() {
return list1.size() + list2.size();
}
}
The you could do
public List<String> modifyMyList(List<String> someList){
return new MergedList(someList, List.of("foo", "bar", "baz"));
}
Both ways will work because in this case java works with the reference of the List but i prefer the secound way because this solution works for pass by value too, not only for pass by reference.
Functionally both are same.
However when you expose your method as an API, second method may give an impression that it returns a new modified list other than the original passed list.
While the first method would make it clear (of-course based on method naming convention) that it will modify the original list (Same object).
Also, the second method returns a list, so ideally the caller should check for a null return value even if the passed list is non null (The method can potentially return a null instead of modified list).
Considering this I generally prefer to use method one over second.

Comparing two comparator objects in Java

If I do the following
myObject.myMethod(myClass.getComparator());
with
public void myMethod(Comparator<? super myOtherObject> comparator) {
if (comparator.equals(myClass.getComparator()) {
//do sth
}
}
and in myClass
static Comparator<ListItem> getComparator() {
return new Comparator<myOtherObject>() {
public int compare(myOtherObjectitem1, myOtherObjectitem2) {
return (Integer.valueOf(myOtherObject.getRating()).compareTo(Integer.valueOf(myOtherObject.getRating())));
}
};
}
then "//do sth" is not gonna be executed. So the objects I get from getComparator the two times are different. How can that be? Is there a chance to see, which comparator "myMethod" gets?
You're calling the equals method on this line:
if (comparator.equals(myClass.getComparator())
Since you haven't defined this method explicitly on your Comparator class (which is an anonymous inner class), this defaults to the version inherited from Object - which considers two references equal only if they are the exact same object.
And your getComparator() method states return new Comparator() { ... }, so it's calling the constructor and creating a new object each time it's called. Thus the result of one call to getComparator will be a distinct object, and hence will not be considered equal to, the result of another call.
I can think of two possible ways to change your code so that the equality test returns true:
Create the comparator only once, and return this same object from
getComparator. This would involve a change somewhat like the
following in myClass:
private static Comparator<ListItem> cmp = new Comparator<myOtherObject>() {
public int compare(myOtherObjectitem1, myOtherObjectitem2) {
return (Integer.valueOf(myOtherObject.getRating()).compareTo(Integer.valueOf(myOtherObject.getRating())));
}
};
static Comparator<ListItem> getComparator() {
return cmp;
}
Provide an explicit equals() implementation (and thus a hashCode() one too, ideally). You can then control exactly which objects are considered equal to one of your comparators. This might be much easier if you define a concrete class for your comparator rather than it being an anonymous inner class.
At the end of the day, though, I fear your approach might not be right. What does it mean for two comparators to be equal to one another? I feel this is an ambiguous concept for anything other than data classes, and I would be hesitant to use the Object.equals method for this.
(For example, if by equality you mean "they will sort lists in the same order", then I'd add a method to your comparator class called isEquivalentSortOrder or something similar. This way you can specify exactly what you mean without having to rely on the woolly definition of "being the same".)
Why not to create inside myClass static variable of Comparator like:
class myClass{
public static Comparator<ListItem> = new Comparator<myOtherObject>() {
public int compare(myOtherObjectitem1, myOtherObjectitem2) {
...
}
};
}

HashMap.containsKey() - how to search for a class?

Hello
if you search in an HashMap<String,String> for a specific value of a key-value-pair, you can write the following:
myHashMap.containsKey(myString);
But how can I manage it if the key is not a string? I have a class which looks like this:
public class Kategorie implements Comparable {
private String name;
public Kategorie() {
super();
}
public Kategorie(String name) {
setName(name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public int compareTo(Object o) {
if (!(o instanceof Kategorie))
throw new ClassCastException();
Kategorie k = (Kategorie)o;
String name = k.getName();
return this.getName().compareTo(name);
}
}
In a map I saved keys and values of this type "Kategorie".
mapKategorieDEundEN.put(new Kategorie(strName_de), new Kategorie(strName_en));
Later in the code, I want to check if there is a key with a specific string.
if (mapKategorieDEundEN.containsKey(searchString)) {
...doesn't work, because the key is not a string but a "Kategorie", that's clear.
Then I tried something like this:
if (mapKategorieDEundEN.containsKey(new Kategorie(searchString))) {
...doesn't work too. I assume that it doesn't find anything because the object is not the "original" object but a new one.
In this case, can I use containsKey at all or do I have to use a loop over the HashMap?
You class should override equals and hashCode, it will work after that.
The HashMap/Hashtable puts the items in "buckets" by using the hashCode of the key, so a new object that represents the same value as another object, and which should be considered as the same object must return the same hashCode. All keys that return the same hashCode will then be considered as candidates, and equals will be invoked on them. It's considered a match if equals returns true.
HashMap uses hashCode() and equals(). You have to implement them. If you don't know how. Check your IDE (eclipse) usually can generate them for you.
If you want to access your objects using your compareTo method, you should not use a hashCode/equals based Map, but a SortedMap, like TreeMap (or ConcurrentSkipListMap).
This has the added benefit that it enables range-based queries (e.g. "give me all categories larger than this one"), but is a bit slower (O(log n) instead of O(1)) for simple get accesses compared to hash-based access (with a good hash code, not a constant one).
For a general use class, defining both hashCode/equals and compareTo would be sensible, then the user of the class can decide which type of map to use. (If there are different ways to sort your objects, better provide different Comparator objects.)
As a side remark, you should not implement Comparable, but Comparable<Kategorie>. Then your compareTo method would look like this:
public int compareTo(Kategorie k) {
String name = k.getName();
return this.getName().compareTo(name);
}

Anything wrong about my Intset Class?

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.

Categories