I am getting an error on .addFirst method, why? - java

import javax.swing.*;
import java.util.*;
import java.awt.*;
public class ConverAryToList {
public static void main(String[] args) {
// TODO Auto-generated method stub
String[] stuff = { "people ", "watermelon ", "melons ", "fudge " };
List<String> list = new java.util.LinkedList<String>(
Arrays.asList(stuff));
list.add("pumpkin");
list.addFirst("first");
stuff = list.toArray(new String[list.size()]);
for (String x : stuff)
System.out.printf("%s", x);
}
}
This is a simple exercise on adding elements to a list. On list.addFirst I get: The method addFirst(String) is undefined for the type List. Where did I go wrong?

Your reference type is the List<T> interface, which does not declare any addFirst method.
You can either set the reference type explicitly as LinkedList<String>:
LinkedList<String> list = new LinkedList<String>(
Arrays.asList(stuff));
Or you can cast:
((LinkedList<String>)list).addFirst("first");
The first methodology is preferred.
Casting is slightly more "dangerous", because it assumes your reference has not been assigned a new value.
For instance, if you assigned list to new ArrayList<String>(); in between the two statements above, you'd get a ClassCastException at runtime.

method addFirst exists on class LinkedList, not on interface List.
Here :
List<String> list = //whatever
list is considered as a List, not a LinkedList
Change it to :
LinkedList<String> list = //whatever

LinkedList implement two interfaces: List And Deque.
Method addFirst is declared in Deque interface.
Deque list = new LinkedList<Number>();
list.addFirst(3);

Related

Collection.sort(arraylist) in a function sorting another arraylist

say, I made an arraylist in (public class class1(String args[]))
static List<Double> list1 = new ArrayList<Double>();
then I pass this arraylist to a function in (public static void main(String args[]))
biggestvalue(list1);
this is the function for example:
public static double biggestvalue(List<Double> list){
Collections.sort(list);
return list.get(list.size()-1);
}
I pass it into a function so that hopefully it will only sort list but not list1, but then list1 gets sorted as well, and I do not understand why that is.
Therefore, please explain to me why that is, and what solutions to this error are out there?
You only pass a reference to the List when you pass it as an argument. Therefore, both list and list1 point to the same List.
A good rule of thumb is to not modify objects passed into a method, so I would make a copy inside the method:
public static double biggestvalue(List<Double> list){
List<Double> temp = new ArrayList<>(list);
Collections.sort(temp);
return temp.get(temp.size()-1);
}
list1 gets sorted as well because you are passing a reference to that object. You want to duplicate the list before sorting it, so the original object doesn't get modified:
List<Double> dup = new ArrayList<>(list);
Collections.sort(dup);
return dup.get(dup.size() - 1);

Implementing a new LinkedList method in Java

I have an assignment that involves creating three methods that manipulate a linked list. The instructions dictate that I use the following constructor:
public MyList (LinkedList<Integer> list) {
...
}
However, Eclipse seems to not like my code regardless of how I try integrate it. Here's my current attempt:
import java.util.*;
public class ListClass {
public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<Integer>();
list.add(10);
list = MyList(list);
}
public MyList (LinkedList<Integer> list){
LinkedList<Integer> r = list;
return r;
}
}
Now I thought that the MyList constructor above would happily just return the list entered, but my Java skills are really weak. I've been going through the tutorials and gave this a go, but it hasn't worked as I thought it would.
Anyway so Eclipse is giving me two errors - at the "list = MyLIst(list);" line it says the method MyList is undefined for ListClass, and at the "public MyList" line it says "the return type for the method is missing" - but I've told it that r is a linked list, and to return that.
This hurts my brain and I can't manage to figure it out, can anyone give me a hand? I think if I were able to get the above code working, I should be able to get the rest sorted.
Newer code
As rightfully pointed out, my class name isn't the same as my supposed constructor name. So here's the adjusted code:
import java.util.LinkedList;
public class MyList {
public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<Integer>();
list.add(10);
list.add(-20);
MyList(list);
}
public MyList(LinkedList<Integer> list) {
LinkedList<Integer> newList = list;
System.out.println(newList);
}
}
This has solved the "return type" error (thank you), though I'm still getting the "undefined" error.
What's missing in the declaration of your method MyList is the return type of the method:
public MyList (LinkedList<Integer> list)
should be something like
public LinkedList<Integer> MyList (LinkedList<Integer> list)
Besides that, the usual convention for method names is camel case, but starting with a lower-case letter. I'd call it myList instead of MyList (you should choose a better name for the method that reflects what the purpose of the method is).
If
public MyList (LinkedList<Integer> list) {
...
}
is supposed to be a Constructor, the class also must be named MyList. You can't return anything from a constructor, so just leave the declaration of it as it is.
Just rename your class, save the LinkedList to a private field in the constructor above, and then add the methods you are supposed to implement to the MyList class.
To get rid of the undefined problem, you need to create your list using 'new':
MyList myList = new MyList(list);
With your modified code, there's still a few things to correct:
In Java, you call a constructor in order to create a new Object. You probably want to keep this object when you create it as part of your main() method, using something like the following in order to prevent your 'undefined' error:
MyList ml = new MyList(list);
As part of your Constructor you only store the LinkedList<Integer> that's passed in as as local variable, and not as a class variable. Correct this with the following declaration at the top of your class:
public class MyList {
private LinkedList<Integer> list;
//...
Structure for additional functionality
In order to add the additional functionality as described in your comment below, I'd use the following sort of structure (Obviously you still need to implement the methods, but you can see where I'd put them):
import java.util.LinkedList;
public class MyList {
private LinkedList<Integer> list;
public MyList(LinkedList<Integer> list) {
this.list = list;
}
public LinkedList<Integer> reverse() {
//Create a reversed list
return rList;
}
public LinkedList<Integer> odd() {
//Create a list of the odd elements
return oddList
}
public LinkedList<Integer> even() {
//Create a list of the even elements
return evenList;
}
#Override
public String toString() {
return list.toString();
}
public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<Integer>();
list.add(0);
list.add(2);
list.add(4);
MyList ml = new MyList(list);
System.out.println("MyList: " + ml);
LinkedList<Integer> tsil = ml.reverse();
System.out.println("Reversed: " + tsil);
LinkedList<Integer> ls = ml.odd();
System.out.println("Odd: " + ls);
LinkedList<Integer> it = ml.even();
System.out.println("Even: " + it);
}
}
The problem here is that a constructor must have the same name of its enclosing class. However, you're trying to name a MyList constructor inside a class named ListClass.
So, either name both your class and the constructor MyList or name them ListClass.
As for the "undefined" issue, you can't directly call a constructor. You have to use it in a "new" statement, as it is used to create new instances of the class:
MyList someList = new MyList(); // variable someList will hold a new MyList instance
or
new MyList(); // instance without a reference variable.

How to return the correct type of list?

If I have a method like this (for simplicity assume integers):
public static List<Integer> doSomething(List<Integer> list) {
// logic here
}
and I need for my processing to create internally a new list which I will create and somehow populate and return to the caller, how can I do it since I don't know what type of list the caller passed in?
I don't want to return a List of different type that what the caller passed in.
E.g. If the caller passed a LinkedList and I don't want to return an ArrayList.
How can this issue best be approached?
You shouldn't tie your implementation to a particular implementation of List, the idea of using an interface is that, from the outside, it shouldn't matter what concrete class you're instantiating as long as it conforms to the List interface.
EDIT :
Anyway, here's a possible way:
List<Integer> lst1 = new ArrayList<Integer>();
Class<?> klass1 = lst1.getClass();
List<Integer> copy1 = (List<Integer>) klass1.newInstance();
System.out.println(copy1.getClass().getName());
> java.util.ArrayList
List<Integer> lst2 = new LinkedList<Integer>();
Class<?> klass2 = lst2.getClass();
List<Integer> copy2 = (List<Integer>) klass2.newInstance();
System.out.println(copy2.getClass().getName());
> java.util.LinkedList
As you can see in the console, the copies are instances of the same class as the original list.
If you can get away with just using one of those two output types, then you can do
if (inputList instanceof RandomAccess) {
// use an ArrayList
} else {
// use a LinkedList.
}
The RandomAccess interface is meant to indicate that the implementation allows O(1) get operations.
Marker interface used by List implementations to indicate that they support fast (generally constant time) random access. The primary purpose of this interface is to allow generic algorithms to alter their behavior to provide good performance when applied to either random or sequential access lists.
By doing this, your APIs allow clients to defend their inputs. They can pass in the result of Collections.unmodifiableList(...) and be sure that it isn't modified by other code.
If you really know the input is a mutable list, you can clone() the list, then clear() it. Both ArrayList and LinkedList have public clone() methods which can be accessed reflectively.
The best thing to do is to remove the list creation from the method. Have the caller decide how to create the list:
public static void doSomething(List<Integer> dest, List<Integer> src) {
You could use Class.newInstance to create a list of the passed in type:
public static List<Integer> doSomething(List<Integer> list)
{
List<Integer> newList = null;
try
{
newList = list.getClass().newInstance();
}
catch(InstantiationException e)
{
throw new RuntimeException(e);
}
catch(IllegalAccessException e)
{
throw new RuntimeException(e);
}
//Logic here
return newList;
}
#Test
public void test()
{
List<Integer> testList = new ArrayList<Integer>();
List<Integer> resultList = doSomething(testList);
Assert.assertEquals(testList.getClass(), resultList.getClass());
Assert.assertNotSame(LinkedList.class, resultList.getClass());
testList = new LinkedList<Integer>();
resultList = doSomething(testList);
Assert.assertEquals(testList.getClass(), resultList.getClass());
Assert.assertNotSame(ArrayList.class, resultList.getClass());
}
If you really, really care what kind of object comes out, I would include that as a parameter to the method, like:
<T extends List<Integer>> T doSomething(Class<T> returnType,List<Integer> v)
throws Exception
{
// constructors for your return will be tricky :)
// returnType.newInstance() will probably work.
T result = returnType.newInstance();
result.add(86); result.add(99);
return result;
}

How to cast ArrayList<> from List<>

Can somebody please explain me why I can't cast List<> to ArrayList<> with first approach and I do with second one? Thank you.
First approach:
ArrayList<Task> tmp = ((ArrayList<Task>)mTrackytAdapter.getAllTasks(token));
Second approach:
ArrayList<Task> tmp = new ArrayList<Task>(mTrackytAdapter.getAllTasks(token));
When you do the second one, you're making a new arraylist, you're not trying to pretend the other list is an arraylist.
I mean, what if the original list is implemented as a linkedlist, or some custom list? You won't know. The second approach is preferred if you really need to make an arraylist from the result. But you can just leave it as a list, that's one of the best advantages of using Interfaces!
When you are using second approach you are initializing arraylist with its predefined values.
Like generally we do
**ArrayList listofStrings = new ArrayList<>();
**
Let's say you have an array with values, now you want to convert this array into arraylist.
you need to first get the list from the array using Arrays utils.
Because the ArrayList is concrete type that implement List interface. It is not guaranteed that method asList, will return this type of implementation.
List<String> listofOptions = (List<String>) Arrays.asList(options);
then you can user constructoru of an arraylist to instantiate with predefined values.
ArrayList<String> arrlistofOptions = new ArrayList<String>(list);
So your second approach is working that you have passed values which will intantiate arraylist with the list elements.
More over
ArrayList that is returned from Arrays.asList is not an actual arraylist, it is just a wrapper which doesnt allows any modification in the list.
If you try to add or remove over Arrays.asList it will give you
UnsupportedOperationException
Try running the following code:
List<String> listOfString = Arrays.asList("Hello", "World");
ArrayList<String> arrayListOfString = new ArrayList(listOfString);
System.out.println(listOfString.getClass());
System.out.println(arrayListOfString.getClass());
You'll get the following result:
class java.util.Arrays$ArrayList
class java.util.ArrayList
So, that means they're 2 different classes that aren't extending each other. java.util.Arrays$ArrayList signifies the private class named ArrayList (inner class of Arrays class) and java.util.ArrayList signifies the public class named ArrayList. Thus, casting from java.util.Arrays$ArrayList to java.util.ArrayList and vice versa are irrelevant/not available.
The second approach is clearly wrong if you want to cast. It instantiate a new ArrayList.
However the first approach should work just fine, if and only if getAllTasks return an ArrayList.
It is really needed for you to have an ArrayList ? isn't the List interface enough ? What you are doing can leads to Runtime Exception if the type isn't correct.
If getAllTasks() return an ArrayList you should change the return type in the class definition and then you won't need a cast and if it's returning something else, you can't cast to ArrayList.
Just try this :
ArrayList<SomeClass> arrayList;
public SomeConstructor(List<SomeClass> listData) {
arrayList.addAll(listData);
}
You can cast List<> to ArrayList<> if you understand what you doing. Java compiler won't block it.
But:
It's bad practice to casting parent type to child type (or interface to implementation type) without checking.
This way better:
if (list instanceof ArrayList<Task>) {
ArrayList<Task> arraylist = (ArrayList<Task>) list;
}
Maybe you don't need implementation type as reference. Look SonarQube warning https://sbforge.org/sonar/rules/show/squid:S1319. You can avoid this casting in the most cases.
You can use Guava method:
ArrayList<Task> arraylist = Lists.newArrayList(list);
The first approach is trying to cast the list but this would work only if the List<> were an ArrayList<>. That is not the case. So you need the second approach, that is building a new ArrayList<> with the elements of the List<>
Because in the first one , you're trying to convert a collection to an ArrayList.
In the 2nd one , you just use the built in constructor of ArrayList
May be:
ArrayList<ServiceModel> services = new ArrayList<>(parking.getServices());
intent.putExtra("servicios",services);
import java.util.List;
import java.util.Arrays;
import java.util.*;
public class Merge
{
public static void main(String[] args) {
// This is normal way
// List<Integer> l1 = new ArrayList<Integer>(); l1.add(2); l1.add(5); l1.add(10); l1.add(22);
// List<Integer> l2 = new ArrayList<Integer>(); l2.add(3); l2.add(8); l2.add(15);
//Array.asList only have the list interface, but ArrayList is inherited from List Interface with few more property like ArrayList.remove()
List<Integer> templ1 = Arrays.asList(2,5,10,22);
List<Integer> templ2 = Arrays.asList(3,8,12);
//So creation of ArrayList with the given list is required, then only ArrayList.remove function works.
List<Integer> l1 = new ArrayList<Integer>(templ1);
List<Integer> l2 = new ArrayList<Integer>(templ2);
List<Integer> l3 = new ArrayList<Integer>();
Iterator itr1 = l1.iterator();
while(itr1.hasNext()){
int x = (Integer) itr1.next();
Iterator itr2 = l2.iterator();
while(itr2.hasNext()) {
int y = (Integer) itr2.next();
if(x < y) {
l3.add(x);
break;
}
else{
l3.add(y);
itr2.remove();
}
}
}
Iterator it = l1.iterator();
while (it.hasNext()){
int k = (Integer) it.next();
if (l3.contains(k)){
continue;
}
else{
l3.add(k);
System.out.println(k);
}
}
Iterator itr2 = l2.iterator();
while (itr2.hasNext()){
int k = (Integer) itr2.next();
l3.add(k);
}
System.out.println(l3);
}
}

How to reclaim the generic type you declared an arraylist to be in Java?

I was just playing around and a thought came to my mind and I decided I want to try it:
Make an ArrayList that holds more ArrayLists.
For example, I created an ArrayList called intList that holds ints, then filled it with values. After that I did a stringList one and filled it too. Then I made an ArrayList that holds other ArrayLists called aList and added intList and stringList to it.
Now the problem I faced was if I was retrieving objects from aList, it would not recognize if the generic type was int or string.
Here is the code I tried:
import java.util.*;
public class Practice {
public static void main(String[] args) {
List<ArrayList> list = new ArrayList<ArrayList>();
ArrayList<int> intList = new ArrayList<int>();
intList.add(1);
intList.add(2);
intList.add(3);
ArrayList<String> stringList = new ArrayList<String>();
stringList.add("One");
stringList.add("Two");
stringList.add("Three");
list.add(intList);
list.add(stringList);
for(ArrayList lst : list) {
for(ArrayList lt : lst) {
System.out.println(lt);
}
}
}
}
Java has "generic type erasure", meaning that the type parameters to generics are "erased". Once you create an ArrayList<T> there's no way to find out what T was.
Only class types can be used as generic type parameters, so you can't have an ArrayList<int>. Use an ArrayList<Integer> instead.
In addition, the types used in your loops are wrong. Since list is a list of lists of values, lst is a list of values, which means that your lt variable will be either an integer or a string, not another ArrayList.
The deeper problem here is that you're still using raw types, so the compiler can't find that error for you. You should declare list as something like List<List<? extends Object>>. That way you can add both an ArrayList<Integer> and an ArrayList<String> to it, and extract the values as type Object within your loop.
Since no type information is stored in generic type, you could get element from sub-list and check it's type:
for(ArrayList subList : list) {
if (subList.size() > 0) {
Class elementClass = subList.get(0).getClass();
// do something else with it
}
}
But:
It will not work, if subList is empty
Generally, the concept of storing several lists of different types in another list looks rather strange.
Type erasure means that at runtime, the type is erased. That's why you can cast from one generic to another:
import java.util.ArrayList;
public class Test {
public static void main(String [] args){
ArrayList<String> list = new ArrayList<String>();
ArrayList list2 = (ArrayList)list;
list2.add(new Integer(5));
System.out.println(list2.get(0).getClass());
}
}
Will output:
class java.lang.Integer
import java.util.*;
public class Practice {
public static void main(String[] args) {
List<ArrayList<?>> list = new ArrayList<ArrayList<?>>();
ArrayList<Integer> intList = new ArrayList<Integer>();
intList.add(1);
intList.add(2);
intList.add(3);
ArrayList<String> stringList = new ArrayList<String>();
stringList.add("One");
stringList.add("Two");
stringList.add("Three");
list.add(intList);
list.add(stringList);
for(ArrayList<?> lst : list) {
for(Object lt : lst) {
System.out.println(lt);
}
}
}
}

Categories

Resources