This question already has answers here:
How do I remove repeated elements from ArrayList?
(40 answers)
Closed 6 years ago.
ArrayList<String> values=new ArrayList<String>();
values.add("s");
values.add("n");
values.add("a");
values.add("s");
In this Array, I want to remove repeated values.
Try this...
ArrayList<String> values=new ArrayList<String>();
HashSet<String> hashSet = new HashSet<String>();
hashSet.addAll(values);
values.clear();
values.addAll(hashSet);
Try below code,
ArrayList<String> values=new ArrayList<String>();
String newValue;
// repeated additions:
if (!values.contains(newValue)) {values.add(newValue);}
HashSet hs = new HashSet();
hs.addAll(demoArrayList); // demoArrayList= name of arrayList from which u want to remove duplicates
demoArrayList.clear();
demoArrayList.addAll(hs);
I think a real neat solution for enforcing unique array lists is this one, if it's not too much code for what you're trying to achieve.
public class UniqueOverridingList extends ArrayList {
public enum LAST_RESULT {
ADD, OVERRIDE, NOTHING;
}
private LAST_RESULT lastResult;
public boolean add(T obj) {
for (int i = 0; i < size(); i++) {
if (obj.equals(get(i))) {
set(i, obj);
lastResult = LAST_RESULT.OVERRIDE;
return true;
}
}
boolean b = super.add(obj);
if (b) {
lastResult = LAST_RESULT.ADD;
} else {
lastResult = LAST_RESULT.NOTHING;
}
return b;
}
public boolean addAll(Collection c) {
boolean result = true;
for (T t : c) {
if (!add(t)) {
result = false;
}
}
return result;
}
public LAST_RESULT getLastResult() {
return lastResult;
}
}
The class David Hedlund suggested can be made a lot shorter:
public class UniqueArrayList extends ArrayList {
/**
* Only add the object if there is not
* another copy of it in the list
*/
public boolean add(T obj) {
if(this.contains(obj))
return false;
return super.add(obj);
}
public boolean addAll(Collection c) {
boolean result = false;
for (T t : c) {
if (add(t)) {
result = true;
}
}
return result;
}
}
The addAll operation is modified too. The documentation states:
Returns: true if this list changed as a result of the call.
I modified the method to reflect this behaviour. There's still one problem. The documentation of the addAll() method also states:
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.
The order might be broken by using this method. A possible workaround for this problem might be not supporting the addAll method.
Related
This question already has answers here:
Check if a value exists in ArrayList
(4 answers)
Closed 2 years ago.
I am trying to loop through an ArrayList, and compare each index value to a default value, if the index value matches the default value, I want to return true, the only problem is that, it always returns true only to the index item that is added. Since my class doesn't have a main method, I have added those values during the class constructor initialization.
public class CountryFinderImpl implements CountryFinder{
List<String> Countries = new ArrayList<String>();
public CountryFinderImpl() {
Countries.add("canada");
Countries.add("japan");
Countries.add("usa");
}
#Override
public boolean forWeather(String country) {
// TODO Auto-generated method stub
country = country.toLowerCase();
boolean c=false;
for(int i=0; i<Countries.size();i++) {
if(Countries.get(i).equals(country)) {
//System.out.println(country+"Weather available");
c=true;
}else {
//System.out.println(country+"weather unavilable");
c=false;
}
}
return c;
}
}
The country parameter is passed from another class, which takes the country value from the user.
In each iteration of the loop, you overwrite c, regardless of its value, so you'll always return the result fot the last element. One solution is to use the "early return" idiom and return true immediatly when the item is found:
#Override
public boolean forWeather(String country) {
country = country.toLowerCase();
for (int i = 0; i < Countries.size() ;i++) {
if (Countries.get(i).equals(country)) {
return true;
}
}
return false;
}
Note, however, that this is just a reimplementation of the contains method, so you might as well just use it:
#Override
public boolean forWeather(String country) {
return Countries.contains(country.toLowerCase());
}
For my data structures class, we have to create our own Stack data type and the implementation for it as a project. The problem I'm running into is when the professor asked us to implement an equals(Object object) method. Heres what I have so far...
package stack;
import list.*;
public class Stack <E>
implements StackADT<E>//the interface
{
List <E> values;
public Stack()
{
values = new ArrayList<E>();
}
public E push(E value)
{
values.add(value);
return value;
}
public E pop()
{
return values.remove(values.size()-1);
}
public E peek()
{
return values.get(values.size()-1);
}
/** #return true only if this Stack is empty */
public boolean isEmpty()
{
return (values.size()==0);
}
/** Clear this stack, to make it an empty stack */
public void clear()
{
for (int i = 0; i < values.size()-1; i++)
{
pop();
}
}
public String toString()
{
String result = "[";
for (int i = 0; i<values.size(); i++)
{
if (i == values.size()-1)
{
result = result + values.get(i);
}
else
{
result = result + values.get(i) +",";
}
}
result = result + "]";
return result;
}
public boolean equals (Object object)
{
if (!(object instanceof StackADT))
{
return false;
}
StackADT <E> otherStack = new Stack<E>();
for(Object o: object)//heres where i run into trouble
{
otherStack.push(o);
}
for (int i=0;i<values.size()-1;i++)
{
if (!(values.get(i).equals(otherStack.pop())))
{
return false;
}
}
return true;
}
}
Our Stack is pretty much an ArrayList which we also built in our class. the problem is, I cant add the Object object into a stack because its not something thats iteratable(?able to be iterated over). Is there a better way to do this? I would think a get() would work, since the Stack I create is an ArrayList, but whenever I use get() on otherStack, it can't find the method. I had a temporary solution when I tried casting object as a stack(I hope im using the right terminology). It looked something like this
Stack otherStack = (Stack) object;
for (int i=0;i<values.size()-1;i++)
{
if (!(values.get(i).equals(otherStack.pop())))
{
return false;
}
}
return true;
}
this seemed to work, but when pop() was called on otherStack, the values in the original list(the one that becomes otherStack) that was passed into the equals() method we're also popped from the original list, leading to an incorrect result. Is there a better way to do this without adding in any other methods? I'm trying to stick as close to the formula set up by my professor as possible, so I dont want to add any extra fields or methods.
any and all help is appreciated
An equals method is not supposed to create anything, not even a temporary object. Rather than creating a new otherStack, cast the object that you have checked to be StackADT, like this:
// This should be the first line of any equals() implementation:
if (object == this) {
return true;
}
// You've got this part right: you need to check the other object's type
if (!(object instanceof StackADT)) {
return false;
}
// Now that you know the type, cast the other object to StackADT<E>
StackADT<E> otherStack = (StackADT<E>)object;
// The next step is to check the sizes:
if (values.size() != otherStack.values.size()) {
return false;
}
// Finally, go through the individual elements in a loop
In the loop that follows, do not pop the other stack. Do not do anything that can modify it. Simply go through the underlying storage (i.e. values), and check elements one by one.
Don't forget to override hashCode as well: you need to do it every time when you override equals for the object to fulfill the contract specified by java.lang.Object.
This question already has answers here:
Avoiding NullPointerException in Java
(66 answers)
Closed 6 years ago.
How to avoid null insertion in ArrayList while inserting element?
ArrayList<String> al=new ArrayList<String>();
al.add(null);//should avoid
.
.
.
al.add("Ramesh");
Avoiding null can be harmful sometimes and it could hide possible bugs.
If you're worried about getting NullPointerException in some stage, you can simply check if the item stored in the ArrayList is null.
You cannot disallow inserting null to ArrayList.
You can try something like that, But if you want to do exactly what you are trying you have to rewrite add() in ArrayList class. Using this validation you can avoid null
public static void main(String[] args) {
ArrayList<String> al=new ArrayList<String>();
al=add(al,null);
al=add(al,"Ramesh");
al=add(al,"hi");
}
public static ArrayList<String> add(ArrayList<String> al,String str){
if(str!=null){
al.add(str);
return al;
}else {
return al;
}
}
In this case you have to call your custom add method to add element
You could create your own ArrayList-Class (derived from the original) and override the Add-Method
Then you could check for null when Adding.
#Override
public boolean add(E e) {
if (e == null) return false;
else return super.add(e)
}
As Mark stated in the comments you perhaps want to override all other possibilties of Adding values too. (see the doc)
add(E e)
add(int index, E element)
addAll(Collection c)
addAll(int index, Collection c)
set(int index, E element)
ArrayList<String> al = new ArrayList<String>() {
#Override
public boolean add(String s ) {
if( s != null ) {
return super.add( s );
}
return false;
}
};
al.add(null);
al.add("blabla");
I'm trying to use a method to compare t2o different lists. Basically I want to pass two different lists to a method which will return true or false if the elements of one array list are contained in the other using .contains. Right now it only returns true - and I'm not sure why. I'd like it to return false. If someone could help me figure this out, that would be great.
public class ArrayListTest {
public static void main(String[] args) {
List<String> list1 = new ArrayList<String>();
List<String> list2 = new ArrayList<String>();
list1.add("cat");
list1.add("dog");
list1.add("zebra");
list1.add("lion");
list1.add("mouse");
//Test Values
//list2.add("cat");
list2.add("lizard");
boolean doesitcontain = contains(list1, list2);
System.out.println(doesitcontain);
}
public static boolean contains (List<String>list1, List<String>list2){
boolean yesitcontains;
for(int i = 0; i < list1.size(); i++){
if(list2.contains(list1.get(i))){
System.out.println("Duplicate: "+list1.get(i));
yesitcontains = true;
System.out.println(yesitcontains);
}else{
yesitcontains = false;
System.out.println(yesitcontains);
}
}
if (yesitcontains = true){
return true;
}else
return false;
}
}
You have inadvertently used the assignment operator where you intended the equality operator. In your specific case you should rewrite all this:
if (yesitcontains = true){
return true;
}else
return false;
}
to just
return yesitcontains;
and avoid any chance of confusion.
Furthermore, your algorithm will not work because you should return true immediately when you see a duplicate. Instead you go on with the loop and "forget" your finding. You can expect this to always return false except if the very last elements coincide.
In a wider context, I should also give you the following general advice:
Avoid indexed iteration over lists. Not all lists are ArrayLists and may show O(n) complexity for get(i). Instead use the enhanced for loop, which is safer, more concise, and more obvious;
Know the library: if you're just after confirming there are no duplicates, just Collections.disjoint(list1, list2) would give you what you need;
Be aware of algorithmic complexity: checking for duplicates in two lists is O(n2), but if you turn one of them into a HashSet, you'll get O(n).
Taking everything said above into account, the following would be an appropriate implementation:
static boolean disjoint(Collection<?> c1, Collection<?> c2) {
for(Object o : c1)
if (c2.contains(o))
return true;
return false;
}
If you look at Collections.disjoint, you'll find this exact same loop, preceded by a piece of code which optimizes the usage of sets for reasons described above.
Seems to me your method should be rewritten to:
public static boolean contains(List<String>list1, List<String>list2) {
return list2.containsAll(list1);
}
The code you currently have actually only checks if the last element of list1 is also in list2.
If you're actually looking for a contains any, this simple solution will do:
public static boolean contains(List<String>list1, List<String>list2) {
for (String str : list1) {
if (list2.contains(str)) {
return true;
}
}
return false;
}
if (yesitcontains = true){
should be
if (yesitcontains == true){
== is for comparison and = is for assignment.
if (yesitcontains = true){
will always evaluate to if(true) which causing return true;
EDIT:
(OR)
simply return yesitcontains; as commented.
if (yesitcontains == true) { } // use `==` here
or just
if (yesitcontains) { }
The below code assigns true to yesitcontains , and the expression will always be true.
if (yesitcontains = true) { }
There is no point of if() in your code , you can simple return yesitcontains;
Why Methode LinkedList.contains() runs quickly than such implementation:
for (String s : list)
if (s.equals(element))
return true;
return false;
I don't see great difference between this to implementations(i consider that search objects aren't nulls), same iterator and equals operation
Let's have a look at the source code (OpenJDK version) of java.util.LinkedList
public boolean contains(Object o) {
return indexOf(o) != -1;
}
public int indexOf(Object o) {
int index = 0;
if (o==null) {
/* snipped */
} else {
for (Entry e = header.next; e != header; e = e.next) {
if (o.equals(e.element))
return index;
index++;
}
}
return -1;
}
As you can see, this is a linear search, just like the for-each solution, so it's NOT asymptotically faster. It'd be interesting to see how your numbers grow with longer lists, but it's likely to be a constant factor slower.
The reason for that would be that this indexOf works on the internal structure, using direct field access to iterate, as opposed to the for-each which uses an Iterator<E>, whose methods must also additionally check for things like ConcurrentModificationException etc.
Going back to the source, you will find that the E next() method returned by the Iterator<E> of a LinkedList is the following:
private class ListItr implements ListIterator<E> {
//...
public E next() {
checkForComodification();
if (nextIndex == size)
throw new NoSuchElementException();
lastReturned = next;
next = next.next;
nextIndex++;
return lastReturned.element;
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
This is considerably "busier" than the e = e.next; in LinkedList.contains! The iterator() of a LinkedList is actually a ListIterator, which has richer features. They aren't needed in your for-each loop, but unfortunately you have to pay for them anyway. Not to mention all those defensive checks for ConcurrentModificationException must be performed, even if there isn't going to be any modification to the list while you're iterating it.
Conclusion
So yes, iterating a LinkedList as a client using a for-each (or more straightforwardly, using its iterator()/listIterator()) is more expensive than what the LinkedList itself can do internally. This is to be expected, which is why contains is provided in the first place.
Working internally gives LinkedList tremendous advantage because:
It can cut corners in defensive checks since it knows that it's not violating any invariants
It can take shortcuts and work with its internal representations
So what can you learn from this? Familiarize yourself with the API! See what functionalities are already provided; they're likely to be faster than if you've had to duplicate them as a client.
I decided to test this and came out with some interesting result
import java.util.LinkedList;
public class Contains {
private LinkedList<String> items = new LinkedList<String>();
public Contains(){
this.addToList();
}
private void addToList(){
for(int i=0; i<2000; i++){
this.items.add("ItemNumber" + i);
}
}
public boolean forEachLoop(String searchFor){
for(String item : items){
if(item.equals(searchFor))
return true;
}
return false;
}
public boolean containsMethod(String searchFor){
if(items.contains(searchFor))
return true;
return false;
}
}
and a JUnit testcase:
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class ContainsTest {
#Test
public void testForEachLoop(){
Contains c = new Contains();
boolean result = c.forEachLoop("ItemNumber1758");
assertEquals("Bug!!", true, result);
}
#Test
public void testContainsMethod(){
Contains c = new Contains();
boolean result = c.containsMethod("ItemNumber1758");
assertEquals("Bug!!", true, result);
}
}
This funny thing is when I run the JUnit test the results are :
- testForEachLoop() - 0.014s
- testContainsMethod() - 0.025s
Is this true or I am doing something wrong ?