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