Reverse a generic list? - java

public static <T> List<T> arrayListReverse(List<T> lst) {
ArrayList reversed= new ArrayList();
for (int i=lst.size()-1;i>=0;i--){
<T> t= lst.get(i);
reversed.add(t);
}
return reversed;
}
I want to be be able to return a list that is a reversed version of the original list. It should be able to work for any type. I keep getting errors when it comes to the t=input.get(i);
Edit: I would like to only use the List interface

public static <T> List<T> arrayListReverse(List<T> lst) {
Collections.reverse(lst);
return lst;
}

<T> should be T:
public static <T> List<T> arrayListReverse(List<T> lst) {
ArrayList reversed= new ArrayList();
for (int i=lst.size()-1;i>=0;i--){
T t = lst.get(i);
reversed.add(t);
}
return reversed;
}

In your code <T> t = should just be T t =, but you could also use a for-each loop and add to the front of your reversed as you iterate forward. And, you shouldn't use raw types (you didn't specify a generic for reversed) and you could use the diamond operator <>. And you could initialize your output list with the same initial size as your input. Something like
public static <T> List<T> arrayListReverse(final List<T> lst) {
List<T> reversed = new ArrayList<>(lst.size());
for (T t : lst) {
reversed.add(0, t);
}
return reversed;
}

You can also use this:
ArrayList reversed = new ArrayList();
reversed=Collections.reverse(startArray);
Documentation:
public static void reverse(List list)
Reverses the order of the elements in the specified list.
This method runs in linear time.
Parameters:
list - the list whose elements are to be reversed.
Throws:
UnsupportedOperationException - if the specified list or its list-iterator does not support the set operation.

If you really want the method to return the same type of list, as is given as parameter, use the following:
public static <T,L extends List<T>> L reverse(L list){
Collections.reverse(list);
return list;
}
This will return a Vector<String>, if you pass a Vector of Strings.
It will return an ArrayList<Something>, if you pass an ArrayList of Somethings.
It will return a LinkedList<Doom>, when you pass a LinkedList of Doom.
I think, you get the idea.
Btw., Madushan Perera`s answer will also return the same Type as passed, but in that case you would have to cast, if assigning to the original variable.

Related

Return same implementation of List as passed in parameter

Let's say I have a function similar to the following:
public static List<Integer> empty(List<Integer> list) {
List<Integer> empty = new ArrayList<>();
return empty;
}
which I want to return a List of the same implementation as the passed in list. For my example function, this is only true if the passed in list is an ArrayList. How do I initialize a List based on the implemenation of list (e.g. so the returned List would be a LinkedList if list was a LinkedList)?
Not sure why you need this. For me, it is a bad design. However, you can do it using reflection:
public static List<Integer> empty(List<Integer> list) throws InstantiationException, IllegalAccessException {
Class<? extends List> c = list.getClass();
return c.newInstance();
}
Note: above example only works if List implementation class have a public accessible empty constructor else you will get an exception.

Java - From a String Type name how to initialize an ArrayList of that Type

May be many of you have several times wanted to do this. Right now I am trying to do it but stuck.
Say, I have a method like this:
private Object getList(String nameofType) {
return new ArrayList<Type>();
/**e.g. It returns ArrayList<java.lang.Double> if nameofType is "java.lang.Double",
/*ArrayList<java.io.File> if nameofType is "java.io.File"**/
}
How can I init an ArrayList like this?
(This doesn't really answer the question; it is just pointing out that a Class<T> parameter is unnecessary simply to create a generic list, as suggested in other answers)
Guava's Lists.newArrayList method looks something like this:
public static <T> ArrayList<T> newArrayList() {
return new ArrayList<>();
}
No type parameter is needed.
List<String> stringList = Lists.newArrayList();
List<Integer> integerList = Lists.newArrayList();
If you need to invoke for a specific type, you can invoke like:
Lists.<MySpecificType>newArrayList();
The closest thing to what you want to do, might be this:
private List getList(String nameofType) {
List list = null;
try {
Class clazz = Class.forName(nameofType); //must be fully qualified, example: "java.lang.Integer"
list = Collections.checkedList(new ArrayList(), clazz);
} catch (ClassNotFoundException e) {
// log exception, etc.
}
return list;
}
This will return an effectively type-checked list, that will throw an exception if you try to insert an object of different type than specified.
You can check it four yourself:
List list = getList("java.lang.Integer");
System.out.println("Inserting Integer");
list.add(new Integer(1));
System.out.println("List: "+ list);
System.out.println("Inserting Long");
list.add(new Long(1));
System.out.println("List: "+ list);
Output:
Inserting Integer
List: [1]
Inserting Long
Exception in thread "main" java.lang.ClassCastException: Attempt to insert class java.lang.Long element into collection with element type class java.lang.Integer
Do you have to use a String-Parameter?
If not, you can use Generics:
private <T> Object getList(Class<T> listType) {
return new ArrayList<T>();
}
Not sure what you are trying to accomplish, but this code satisfies your needs i believe
public <T> List<T> getList(Class<T> clazz) {
return new ArrayList<T>();
}
It returns a properly List<T> based on the class you pass to its parameter.
Using a string as a parameter does not really help the compiler. Keep in mind that the type information for parameterised types (using generics) are erased at run-time (https://docs.oracle.com/javase/tutorial/java/generics/erasure.html).

How to create a method that retrieves a sublist containing elements of a specific class T?

I have the following function
public <T> T getItemsByType(){
T[] retarr = null;
for(int i = 0; i<items.size(); i++){
if(items.get(i).get instanceof T){
}
}
return null;
}
I need my function to search in a list of items for instances of type T and then return an array of T.
Of course, this would've been great if worked but the problem is that:
Cannot perform instanceof check against type parameter T. Use its erasure Object instead since further generic type information will be erased at runtime
What should I do to obtain the same effect?
You need to pass Class<T> clazz as argument to your method, then use it to check if the element can be assignable to that class by using Class#isInstance.
public <T> T getItemsByType(Class<T> clazz) {
T[] retarr = null;
for(int i = 0; i<items.size(); i++){
if(clazz.isInstance(items.get(i))){
//do your logic here...
}
}
return null;
}
Some recomendations:
It would be better returning a List<T> or Collection<T> instead of returning a single T element.
Avoid returning null, so you don't have to do null-defensive programming.
Use an iterator or an enhanced for loop to traverse through all the elements in your list.
So, a better implementation would be:
public <T> List<T> getItemsByType(Class<T> clazz) {
List<T> theList = new ArrayList<T>();
//using Object since you never specified which type of elements holds this list
for (Object o : items) {
if(clazz.isInstance(o)) {
//do your logic here...
theList.add(clazz.cast(o));
}
}
return theList;
}

Initializing a Set with an Iterable

I want to initialize a Set Implementation (HashSet) in Java with an Iterable. However, the constructor of HashSet doesn't accept Iterables, but only Collections type objects.
Is there a way to convert from Iterable to some subtype of Collections.
You can use Guava.
Set<T> set = Sets.newHashSet(iterable);
or to make it read like a sentence static import,
import static com.google.common.collect.Sets.*;
Set<T> set = newHashSet(iterable);
HashSet constructor relies on more than what Iterable offers: it wants to know the size of the collection up front in order to optimally construct the underlying HashMap. If you have a true, austere Iterable, which doesn't know its size, then you'll have to realize the Iterable up front by turning it into a regular Collection in any of a number of obvious ways.
If, on the other hand, you have a richer object that already knows its size, then it would pay to create a minimalist adapter class that wraps your Iterable into a collection, implementing just size in addition to forwarding the call to iterator.
public class IterableCollection<T> implements Collection<T>
{
private final Iterable<T> iterable;
public IterableCollection(Iterable<T> it) { this.iterable = it; }
#Override public Iterator<T> iterator() { return iterable.iterator(); }
#Override public int size() { return ... custom code to determine size ... }
#Override .... all others ... { throw new UnsupportedOperationException(); }
}
Sure, it's shown in this answer. Basically, iterate over the iterable and copy its contents in a collection:
public static <T> List<T> copyIterable(Iterable<T> iterable) {
Iterator<T> iter = iterable.iterator();
List<T> copy = new ArrayList<T>();
while (iter.hasNext())
copy.add(iter.next());
return copy;
}
Use it as follows, the resulting List object can be passed as a parameter to the HashSet constructor.
Iterable<Integer> list = Arrays.asList(1, 2, 3);
List<Integer> copy = copyIterable(list);
Set<Integer> aSet = new HashSet<Integer>(copy);
EDIT
I've been mistaken all along. Iterable is a superinterface of Collection, so a simple (but unsafe) cast will do the trick, as long as the Iterable was a Collection to begin with.
Iterable<Integer> list = Arrays.asList(1, 2, 3);
Set<Integer> aSet = new HashSet<Integer>((Collection)list); // it works!
The Iterable interface allows the "foreach" syntax to work, so the cleanest way is likely:
public <T> Set<T> toSet(Iterable<T> collection) {
HashSet<T> set = new HashSet<T>();
for (T item: collection)
set.add(item);
return set;
}
Just add each one.
public static <T> Set<T> setFromIterable(Iterable<T> i) {
HashSet<T> set = new HashSet<T>();
Iterator<T> it = i.iterator();
while (it.hasNext()) {
set.add(it.next());
}
return set;
}
Iterable<Integer> someIterable = ...;
Set<Integer> someSet = setFromIterable(someIterable);
Note that you don't use the constructor new HashSet<Integer>(someIterator), because that doesn't exist. Just call the static method.
I use this one-liner (with Java 8+), which only relies on java.util.stream:
StreamSupport.stream(myIterable.spliterator(), false).collect(Collectors.toSet());
// or with static imports:
stream(myIterable.spliterator(), false).collect(toSet());
Putting somewhat a repeated answer for conciseness. Below worked for me for converting the Iterable of String type to a Set(Java8).
Iterable<String> stringIterable = Arrays.asList("str1", "str2", "str3");
Set<String> stringHashSet = new HashSet<>((Collection<? extends String>) stringIterable);

What is the best way to define Generic Method in Java?

I want to define generic static method in my one of project.
Requirement is to method return type to be one of method parameter.
The below is my solution.
public static <T> List<T> convertMapToAttribute(Class<T> attrClass, T attr) {
List<T> list = null;
if (attrClass.equals(String.class)) {
list = (List<T>) new ArrayList<String>();
list.add(attr);
} else if (attrClass.equals(Integer.class)) {
list = (List<T>)new ArrayList<Integer>();
list.add(attr);
}
return list;
}
I have two questions.
Can we avoid this waring "warning: [unchecked] unchecked cast"
without adding #SuppressWarnings("unchecked")?
Is there any other elegant way to solve this above problem
The following should work fine:
List<T> list = new ArrayList<T>();
List<T> list = new ArrayList<>(); // Java 7
Couldn't you just do something like...
public static <T> List<T> convertMapToAttribute(Class<T> attrClass, T attr) {
List<T> list = new ArrayList<T>(1);
list.add(attr);
return list;
}
instead?
UPDATE based on feedback
public static <T> List<T> convertMapToAttribute(T attr) {
List<T> list = new ArrayList<T>(1);
list.add(attr);
return list;
}
By having Class<T> as a parameter, the way to do a checked cast (and skip the annoying warning) is to invoke attrClass.cast() which will throw ClassCastException if the casting fails. In this case, T should be either String or Integer.
The problem here is that you're doing an unchecked cast from a list of T to a list of either String or Integer when you should define the list directly and add the element using a cast:
if (attrClass.equals(String.class)) {
List<String> list = new ArrayList<String>();
list.add(attrClass.cast(attr));
}
And the same goes for Integer.
There's something weird with your method tough (I don't understand the intention, actually), you're creating a list of elements from a type that you're also passing a parameter... Shouldn't this work as well? (since you create a list of T types and add an element of T type).
public static <T> List<T> convertMapToAttribute(T attr) {
List<T> list = new ArrayList<T>();
list.add(attr);
return list;
}
Not to my knowledge
Skip the attrClass parameter, since it actually makes the method non-generic.

Categories

Resources