addAll() method from ArrayList <E> class does not work - java

I am struggling with understanding why the addAll() method from ArrayList does not work.
I have my class:
public class XList<E> extends ArrayList<E> {...
}
With a method:
public XList<E> union(XList<E> input) {
System.out.println(this);//
System.out.println(input);
this.addAll(input);
return this;
}
System.out.println indicates, that correct values are in the given lists, but after adding, "this" does not get updated, and is returned without modification.
Could you please clue me in, on the root of the problem?
Any help greatly appreciated.
SSCCE:
public class Main {
public static void main(String[] args) {
XList<Integer> list1 = new XList<>(1, 3, 9, 11);
XList<Integer> list2 = XList.of(5, 6, 9);
List<Integer> m1 = list1.union(list2);
System.out.println(m1);
}
}
class XList<E> extends ArrayList<E> {
private List<E> lista;
public XList(E a, E b, E c) {
lista = new ArrayList<>();
lista.add(a);
lista.add(b);
lista.add(c);
}
public XList(E a, E b, E c, E d) {
lista = new ArrayList<>();
lista.add(a);
lista.add(b);
lista.add(c);
lista.add(d);
}
static XList of(Integer a, Integer b, Integer c) {
return new XList(a, b, c);
}
public XList<E> union(XList<E> input) {
System.out.println("this: " + this);
System.out.println("input: " + input);
this.addAll(input);
return this;
}
public String toString() {
return lista.toString();
}

Your problem is that your XList confusingly both extends ArrayList and also contains a list as a field. That means that XList basically is two separate lists: it's a list itself and it also includes a different separate list
If I were you I'd remove "extends ArrayList" and replace
this.addAll(input);
With
this.lista.addAll(input.lista);

Related

Retrieve ArrayList object by parameter value [duplicate]

This question already has answers here:
How to find an object in an ArrayList by property
(8 answers)
Closed 4 years ago.
I am maintaining a sorted ArrayList of objects (by overwriting the add method as shown here) where each object has 2 attributes: a and b. How can I retrieve an object for which a equals 5?
I cannot use a map, because the value which I want to sort the list on must be able to accept duplicates (which is why this answer is not applicable here).
Code:
class TimeMap {
List<MyType> list = new ArrayList<KVT>() {
public boolean add(KVT mt) {
int index = Collections.binarySearch(this, mt, new SortByTime());
if (index < 0) index = ~index;
super.add(index, mt);
return true;
}
};
}
class KVT{//value-timestamp object
String value;
int timestamp;
public VT(String v, int t){
value=v;
timestamp=t;
}
}
class SortByTimestamp implements Comparator<KVT>{
public int compare(KVT a, KVT b){
return a.timestamp.compareTo(b.timestamp);
}
}
I have written a small example using java8 streams where you can get the object from the ArrayList by a property of the object.
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Test> list = Arrays.asList(new Test(1, 2), new Test(5, 6), new Test(3, 4));
Test test = list.stream().filter(obj -> obj.a == 5).findFirst().orElse(null);
System.out.println(test.a);
}
}
class Test {
int a;
int b;
Test(int a, int b) {
this.a = a;
this.b = b;
}
}
Hope this will give you an idea
Here is an mcve demonstrating retrieval by timestamp as well as some other enhancement:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class TimeMap {
private List<KVT> list;
TimeMap() {
list = new ArrayList<>() {
#Override
public boolean add(KVT mt) {
super.add(mt); //add
Collections.sort(this, new SortByTimestamp()); //resort after add
return true;
}
};
}
boolean add(KVT mt){return list.add(mt);}
KVT getByTimeStamp(int timestamp){
for(KVT mt : list){
if(timestamp == mt.timestamp)
return mt;
}
return null;
}
//returns a copy of list
List<KVT> getListCopy() { return new ArrayList<>(list) ;};
//test
public static void main(String[] args) {
TimeMap tm = new TimeMap();
tm.add(new KVT("A", 2));
tm.add(new KVT("B", -3));
tm.add(new KVT("C", 1));
System.out.println(tm.getListCopy());
System.out.println(tm.getByTimeStamp(1));
}
}
class KVT{
String value;
int timestamp;
public KVT(String v, int t){
value=v;
timestamp=t;
}
#Override
public String toString(){ return value+" ("+timestamp+")";}
//todo add getters
}
class SortByTimestamp implements Comparator<KVT>{
#Override
public int compare(KVT a, KVT b){
//compareTo can not be applied to primitives
return Integer.valueOf(a.timestamp).compareTo(b.timestamp);
}
}

How to cast a Generic ArrayList to a Generic Array

When I call printArray in my pvsm, the error I keep receiving is:
Exception in thread "main" java.lang.ClassCastException:
java.base/[Ljava.lang.Object; cannot be cast to java.base/[Ljava.lang.Integer
I know the problem is with the R[] result = (R[]) list.toArray(). I have no idea how to convert the ArrayList to an array and cast it to a generic at the same time. Note I cannot change the parameters of the function map or add any new functions.
public class Homework2 {
public static void main(String[] args){
Function<Integer,Integer> function = new CalculateSuccessor();
Double[] d= {2.0,4.0,8.0};
Integer[] i= {2,4,8};
printArray(map(function,i));
}
#SuppressWarnings("unchecked")
public static <R,D> R[] map(Function<R,D> function, D[] array){
ArrayList<R> list = new ArrayList<>();
for (D element: array){
list.add(function.apply(element));
}
// THIS LINE OF DAMN CODE
R[] result = (R[]) list.toArray();
return result;
}
public static <R> void printArray(R[] array){
System.out.print("{ ");
for (R element: array){
System.out.print(element + ", ");
}
System.out.print("}");
}
public static class CalculateSuccessor implements Function<Integer,Integer> {
#Override
public Integer apply(Integer parameter) {
return parameter * 2;
}
} //End CalcSuc
} //End Homework2
In another class I have
public interface Function<R,D> {
public R apply(D parameter);
}
which you need for the function.apply. My professor insisted we use this instead of importing Function.
Part one, you need the Class<R> in order to dynamically create an array R[]. I would prefer Arrays.toString over implementing my own version of that. I also needed a Function<D, R> (not a Function<R, D>). But making those changes like
public static void main(String[] args) {
Function<Integer, Integer> function = new CalculateSuccessor();
Double[] d = { 2.0, 4.0, 8.0 };
Integer[] i = { 2, 4, 8 };
System.out.println(Arrays.toString(map(Integer.class, function, i)));
}
public static <R, D> R[] map(Class<R> cls, Function<D, R> function, D[] array) {
ArrayList<R> list = new ArrayList<>();
for (D element : array) {
list.add(function.apply(element));
}
return list.toArray((R[]) Array.newInstance(cls, list.size()));
}
I get
[4, 8, 16]
You can extract the type information from the Function<D,R> because you implemented it with an actual class. So together with #Elliott Frisch answer.
public static <R, D> R[] map(Function<D, R> function, D[] array) {
ArrayList<R> list = new ArrayList<>();
for (D element : array) {
list.add(function.apply(element));
}
Class<?> componentClass = extractReturnType(function)
return list.toArray((R[]) Array.newInstance(componentClass, list.size()));
}
private static Class<?> extractReturnType(Function<?, ?> function) {
Type[] interfaces = function.getClass().getGenericInterfaces();
for(Type iface:interfaces) {
if (iface instanceof ParameterizedType && Function.class.equals(((ParameterizedType) iface).getRawType())) {
return (Class<?>) ((ParameterizedType) iface).getActualTypeArguments()[1];
}
}
throw new IllegalArgumentException("Unable to extract type information");
}

Getting only first element of ArrayList that matches condition

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);

Implementing a List data structure in java

I have a homework about implementing lists in java. I have written a code, and a method about displaying the elements, but when I run it, it says there is an error in this method. can you please help me fix this?
here is my code:
public class Lista {
public int num;
public Lista pas;
public Lista(int num){
this.num = num;
}
public void display(){
System.out.println(num);
}
public static void main(String[] args){
linkedList l = new linkedList();
l.insertfirst(1);
l.insertfirst(3);
l.insertfirst(5);
l.display();
}
}
class linkedList{
public Lista LIST;
public Lista pozicion;
linkedList(){
LIST = null;
}
public void insert(int num, Lista pozicion){
Lista temp = pozicion.pas;
Lista l = new Lista(num);
pozicion.pas.num = num;
pozicion.pas.pas = temp;
}
public void delete(Lista pozicion){
pozicion.pas = pozicion.pas.pas;
}
public Lista locate(int num, Lista LIST){
pozicion = LIST;
while (pozicion.pas != null){
if (pozicion.pas.num == num){
return pozicion;
}else{
pozicion = pozicion.pas;
}
}
return pozicion;
}
public void insertfirst(int num){
Lista eRe = new Lista(num);
eRe.pas = LIST;
LIST = eRe;
}
}
Well, for starters...
display() is not a method of class linkedList (note: naming convention should be LinkedList).
display() is a method of Lista. That is why the IDE is telling you 'display() is undefined for the type linkedList'
Just quickly looking at your code for what you need to do... You need to implement a get() (or perhaps a solution to get the first element of the linkedList and from there iterate through the linkedList) method in the linkedList class which returns a Lista object. With that Lista object, you can then call the method .display() on it.

Error "no suitable method found" when sorting List in Java

I am trying to sort a List of Integer's after converting a List of String's into an Integer List. It gives me this error:
no suitable method found for sort(List,StringToInteger.CustomComparator)
Here is my code:
public class StringToInteger {
public static void main(String args) {
List<String> strList = new ArrayList<String>();
strList.add("34");
strList.add("14");
strList.add("42");
strList.add("24");
List<String> resultList = getIntegerArray(strList);
System.out.println("before sorting"+resultList);
Collections.sort(resultList, new CustomComparator());
System.out.println("after sorting"+resultList);
}
private static List<Integer> getIntegerArray(List<String> stringArray) {
List<Integer> result = new ArrayList<Integer>();
for(String stringValue : stringArray) {
try {
//Convert String to Integer, and store it into integer array list.
result.add(Integer.parseInt(stringValue));
} catch(NumberFormatException nfe) {
//System.out.println("Could not parse " + nfe);
Log.w("NumberFormat", "Parsing failed! " + stringValue + " can not be an integer");
}
}
return result;
}
class CustomComparator implements Comparator<List<Integer>> {
#Override
public int compare(List<Integer> o1, List<Integer> o2) {
return o1.get(1).compareTo(o2.get(1));
}
}
}
You are comparing Lists of Integers in your CustomComperator, while you should be comparing Integers.
You can sort the List also with
Collections.sort(resultList);
or
Collections.reverse(resultList);
List<String> resultList = getIntegerArray(strList);
change this line to
List<Integer> resultList = getIntegerArray(strList);
and this
class CustomComparator implements Comparator<List<Integer>> {
#Override
public int compare(List<Integer> o1, List<Integer> o2) {
return o1.get(1).compareTo(o2.get(1));
}
}
to
class CustomComparator implements Comparator<Integer> {
#Override
public int compare(Integer>o1, Integer o2) {
return o1.compareTo(o2);
}
}
Read the sort method prototype !
public static <T> void sort(List<T> list, Comparator<? super T> c) {
Your code do that:
Collections.sort(resultList, new CustomComparator());
Which is:
Collections.sort(List<String>, Comparator<List<Integer>>);
getIntegerArray returns a List<Integer>. Your compiler should warn you or throw an error.
By the sort contract, it expect a Comparator<? super String>. A Comparator<List<Integer>> is not a Comparator<? super String>.
For the rest, the other answers complete my answer.

Categories