I am creating a class, Doubly Linked List with ListNode as innerclass.
public class DoublyLinkedList<Integer> {
/** Return a representation of this list: its values, with adjacent
* ones separated by ", ", "[" at the beginning, and "]" at the end. <br>
*
* E.g. for the list containing 6 3 8 in that order, return "[6, 3, 8]". */
public String toString() {
String s;
ListNode i = new ListNode(null, null, *new Integer(0)*);
Why is it that I get the error, cannot instantiate the type Integer?
The Integer in your class definition is generic type parameter which hides the Integer wrapper class.
So, new Integer(0) you use inside the class is taking Integer as type parameter, and not the Integer type itself. Since, for a type parameter T, you can't just do - new T();, because the type is generic in that class. Compiler doesn't know what type exactly it is. So, the code is not valid.
Try changing your class to:
public class DoublyLinkedList<T> {
public String toString() {
ListNode i = new ListNode(null, null, new Integer(0));
return ...;
}
}
it will work. But I suspect that you really want this. I guess you want to instantiate the type parameter inside your generic class. Well, that's not possible directly.
You pass the actual type argument while instantiating that class like this:
DoublyLinkedList<Integer> dLinkedList = new DoublyLinkedList<>();
P.S: It would be better if you explain your problem statement clearly, and put some more context into the question.
Related
I am new to Java and writing a method for a generic Linked List that accepts another Linked List as a parameter. As I understand, this new Linked List should be of the same type as the Linked List calling the method.
So, instead of
public void insertList(MyLinkedList<AnyType> otherList, int idx) {
I should be specifying the type of otherList to match the list that calls insertList()?
list.insertList(MyLinkedList<???>, 0);
How would I do this if I don't know the type of list, since it's generic, but know that otherList needs to be the same type? I hope that makes sense. As I mentioned, I am new to Java, so if I am misunderstanding generics, please correct me. Thank you.
I am inferring that you are writing your own linked list and that your declaration looks something like this:
class MyLinkedList<T> {
…
If so, the <T> means that your class has a generic type variable, T, that represents the type of the list's elements.
Given that, the insert method could look something like this:
void insertList(List<? extends T> list, int index) {
/* Count links to find the insertion point */
/* Remember the link that used to follow */
…
for(T obj : list) {
/* Create link for obj and link it to previous */
/* Update previous */
…
}
/* Attach the old link you remembered to previous */
…
}
Here, ? extends T means that you accept anything that extends the generic type of your list.
There's no need to require the collection of inserted elements to be MyLinkedList, or even List—it could be any type of collection that you could iterate.
For what I understand you have sue that the object passed to the function will be a LinkedList, even if you did not know you could make use of 'instanceof' to test if the object is an instance of some type, after you can make use of "cast" resources to "transform" an generic object to another type.
Se the code bellow and adapt for your use.
public static void main(String[] args) {
List<Banana> lista = new LinkedList<Banana>();
testingAndCastingSomeObject(lista);
}
/**
* This method will receive a generic object and test if it is a LinkedList, if it is it will cast the object "transforming" it in a LinkedList
* Afte this I can make what I want
* #param object
*/
static void testingAndCastingSomeObject(Object object) {
LinkedList<?> test = null;
if(object instanceof LinkedList<?>) {
test = (LinkedList<?>) object;
}
//If the List is not empty and the first objetct is a Banana I can cast it too
if(!test.isEmpty() && test.get(0) instanceof Banana ) {
Banana banana = (Banana) test.get(0);
System.out.println("Here is my banana: " +banana);
}
}
public class Banana{
//Banana members and methods
}
class Matrix<T>{
private List<Attribute<T>> attributes;
public Matrix(T type){
attributes = new ArrayList<Attribute<T>>();
attributes.add(new Attribute<T>(type));
}
}
I feel like in the constructor, these two lines should be use a specific type, not the generic T:
attributes = new ArrayList<Attribute<T>>();
attributes.add(new Attribute<T>(type));
But the compiler doesn't complain. So this is the right way to define this class?
Yes, thats the right way. The only thing where you might be wrong is that your Parameter in the constructor should not be namend type, but value. The Type is T.
If you need to, you can say that your Generic has to a childtype of something else. Let's say we have a class which holds an Exception. We could just make a Membervariable of Type Exception. But when getting the Exception from inside this Object, we don't want to cast our Exception to a more specific one.
So we use a Generic which must be a childtype of Exception:
public class SomeClass<T extends Exception>
{
private final T value;
public SomeClass(T value)
{
this.value = value;
}
public T getValue()
{
return this.value;
}
}
Now we can do stuff like this:
SomeClass<ArrayIndexOutOfBoundsException> obj = new SomeClass<>(new ArrayIndexOutOfBoundsException());
ArrayIndexOutOfBoundsException exc = obj.getValue(); // no cast from Exception to ArrayIndexOutOfBoundsException needed
I feel like in the constructor, these two lines should be use a specific type, not the generic T
No, because your class Matrix is generic on the type parameter T. This means that it encapsulates a list of attributes of the type T, namely: List<Attribute<T>>.
If you use it with Integer:
Matrix<Integer> integerMatrix = new Matrix<>(1);
Then 1 would be inside the first attribute of the list.
However, if you declare another matrix with String:
Matrix<String> stringMatrix = new Matrix<>("hello");
Then your matrix will hold attributes that encapsulate String values.
I want to ask you how a single method can return different types of objects in java?
lets say we have a class "a". class a is parent class of classes "b" and "c".
lets say we have an array list defined as:
java.util.ArrayList<a> list;
so this list can contain objects of class a, class b and class c.
lets say we create one object of class b, and one object of class c, and we add them to list.
now, i want to create a method like this:
public ? get_element(boolean first)
{
if (first)
{
return list.get(0);
}
else
{
return list.get(1);
}
}
my problem is, that i do not know what to put at the place of "?" in this method.
if i put "a", so, "public a get_element", when element is returned it is always of type "a", no matter if element was originally of type "b" or "c" when it was added.
but i want that element returned is of type of element added.
so, if i add element of type "b" at index 0 of the list, and element of type "c" at index 1, i wish when i call get_element method, that if i provide parameter equal to "false", that returned element is of type "c", and if i provide true when i call it, that returned element is of type b.
of course, i can cast returned element to the type i wish. but this is just simple example i wrote, but i for real have much more complex situation. i have about 10 classes which all extend one class, and array list which can contain any of those 11 types of objects, and they can be arranged in any way, so i can not know what type of element is at which position, unless i create a code which will try to cast to all types, one by one until it finds the one to which it can cast.
but i want to know, is there some kind of more easy way to do so?
to simplify my question, i wrote this .java file:
public class test
{
public static class a{}
public static class b extends a{}
public static class c extends a{}
public static java.util.ArrayList<a> list = new java.util.ArrayList<a>(2);
static
{
b first_object = new b();
c second_object = new c();
list.add(first_object);
list.add(second_object);
b first_returned_object = get_element(true);
c second_returned_object = get_element(false);
}
public static ? get_element(boolean first)
{
if (first)
{
return list.get(0);
}
else
{
return list.get(1);
}
}
}
my problem is that i do not know what to put before "get_element" in get element method.
what should i put in order that i can save object of type b in "first_returned_object", and object of type c in "second_returned_object"?
of course, this is just example, i would not use these classes, because they are useless, but i wrote this to make my question as simple as possible.
my real classes where i have this kind of problem have 5000+ lines, so i could not include those here, so i wrote the simplest possible version which demonstrates my problem.
any suggestions?
thanx.
post scriptum:
to caps lock haters: your hate is bidirectional here. ;)
You can use Generics to some what make the return type dynamic.
Try this one:
public static <Type> Type get_element(int index)
{
String s = list.get(index).getClass().toString(); // returns "class class_name"
String[] split = s.split(" ");
Class<?> theClass = Class.forName(split[1]); // You need "class_name"
return (Type) theClass.cast(list.get(index));
}
or simply:
public static <Type> Type get_element(int index)
{
return (Type) list.get(index);
}
I am trying to understand some source code. How do I call this method in main?
public void introSort(T[] array, int max_depth)
{
System.out.println(array.length);
}
I simply want to return the length of the given array in my main method. If this is any help, the method is in a class with this declaration:
public class IntroSort<T extends Comparable<T>> extends AbstractSort<T> {
[I understand that this is of generic type, but my understanding of that concept in Java is too minimal for me to answer my questions.]
The type of the array element is the type variable T of the class IntroSort. This is an example for an instance of IntroSort with the type parameter set as Integer:
Integer[] array = {1, 2, 3, 4};
IntroSort<Integer> obj = new IntroSort<>();
obj.introSort(array, 1);
The compiler would match T with Integer based on the declaration of IntroSort, which also means that the array must be of type Integer.
The T is just referring back to the T in your class specification.
If you have an instance of IntroSort, just call the method on it with the same type of array as you instantiated the class with.
I have a generic method (called map) which takes a parameter of type Funcn where Funcn<K,T> is an interface having only one method, T eval(K), which takes a K and returns a T. In map, I need use the Funcn to iterate through a List<K> (which is defined in the main method — I use this in the map to access it) and apply the Funcn to each element in the list. Finally, a new List<T> of all the results of eval should be returned. However, I am not sure how this can be done, since I am unfamiliar with the syntax of generics.
/// the Funcn interface ///
package arrayList;
import java.util.*;
public interface Funcn <K,T> {
public T eval(K k);
}
/// the generic map method(in its own class) ///
public java.util.ArrayList<T> map(Funcn<T,K> fn){
for(T value:this){
//fn must be applied to all elements in 'this'
}
}
The problem in your code
In your code, the interface Funcn<K,T> declares a method eval that takes a K as an argument and returns a T. Note that K is the first type parameter and T is the second.
public interface Funcn <K,T> {
public T eval(K k);
}
In the declaration of your map method, though, you've got the type parameters to your Funcn reversed:
public java.util.ArrayList<T> map(Funcn<T,K> fn){ /* … */ }
// * *
This means that fn.eval takes a T and returns a K. Instead, it should be Funcn<K,T> fn so that fn.eval takes a K and returns a T. This would explain the error message that you mentioned in a comment: "The method apply(K) in the type Function<T,K> is not applicable for the arguments (T)" (It wouldn't explain why you've got Function in one place and Funcn in another, though. Are you showing us the real code?)
In general
Swapping the order of those arguments will solve your immediate problem, but in general the type parameters are a little bit more complicated. It's tricky to get the input and output types for these generic functions exactly right, since you should be able map a function that expects an argument of type C over a list whose elements are of a subtype of C. The comments in the code explain this in a bit more detail.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class MapExample {
/**
* A Function maps an input to an output.
*/
interface Function<InputType,OutputType> {
OutputType call( InputType input );
}
/**
* Map returns a list of elements obtained by applying the function
* to each element of the input list. The input and output types
* of the function do not need to align exactly with the type of
* elements in the input list; but the function's input type must
* be some supertype of the element type of the input list. Similarly,
* the output type of the function does not need to be the element type
* of the output list; but it must extend that type so that the result
* of the function can be stored in the output list.
*/
public static <OutputType,InputType> List<OutputType> map(
final Function<? super InputType,? extends OutputType> function,
final List<? extends InputType> list ) {
final List<OutputType> results = new ArrayList<>( list.size() );
for ( InputType in : list ) {
results.add( function.call( in ));
}
return results;
}
public static void main(String[] args) {
// f takes an integer n to the string "*<n+1>*" (where <n+1> is the value of n+1).
Function<Integer,String> f = new Function<Integer, String>() {
#Override
public String call(Integer input) {
return "*"+new Integer( input + 1 ).toString()+"*";
}
};
System.out.println( map( f, Arrays.asList( 1, 3, 6, 8 )));
}
}
The output is:
[*2*, *4*, *7*, *9*]
(Optional) A case for instance initializers
As an aside, I find that some of these functional problems are nice places to use instance initialization blocks in objects. While the implementation above creates the results list, then populates, and then returns it, you could also have the body of map be:
return new ArrayList<OutputType>( list.size() ) {{
for ( final InputType in : list ) {
add( function.call( in ));
}
}};
which I kind of like, although you'll get a warning about the fact that the new (anonymous) class doesn't have a serialization ID, so you'd either need to #SuppressWarnings("serial") on the map method, or add an ID to the class. Those might not be so desirable, though. There are other issues with this kind of object too, though, as discussed in Efficiency of Java "Double Brace Initialization"?.
I assume that T is the input of Funcn, and K the return type of it. It then has to return a list of K to work, else the generic signature of Funcn is useless.
public java.util.ArrayList<K> map(Funcn<T,K> fn){
ArrayList<K> lst = new ArrayList<K>();
for(T value:this){
lst.add( fn.eval(value) );
}
return lst;
}