java downcast results in method not applicable error - java

I am trying to downcast a function for my database objects. I get:
The method GetAsStringArray(HashMap<Long,dbObject>) in the type
dbObject is not applicable for the arguments
(HashMap<Long,dbEmployee>)
when I try to call GetAsStringArray(). Here is my test code:
dbObject base class:
public class dbObject implements Comparable<dbObject> {
protected long id;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public static dbObject[] GetAsArray(HashMap<Long,dbObject> map) {
Collection<dbObject> list = map.values();
dbObject[] ar = list.toArray(new dbObject[] {});
Arrays.sort(ar);
return ar;
}
public static String[] GetAsStringArray(HashMap<Long,dbObject> map) {
Vector<String>vStrings = new Vector<String>();
Collection<dbObject> list = map.values();
dbObject[] ar = list.toArray(new dbObject[] {});
Arrays.sort(ar);
for (dbObject o : ar)
vStrings.add(o.toString());
return (String[]) vStrings.toArray(new String[] {});
}
#Override
public int compareTo(dbObject another) {
return (int)(this.getId() - another.getId());
}
}
Child class dbEmployee:
public class dbEmployee extends dbObject {
private String First;
private String Last;
public dbEmployee(){}
public String toString() {
return Last + ", " + First;
}
}
And the error:
public static void main(String[] args)
{
HashMap<Long,dbEmployee>mapEmployees = new HashMap<Long,dbEmployee>();
dbEmployee.GetAsStringArray(mapEmployees);
}
Note: some of my dbObjects will have their own compareTo() function (a few of the objects have a field in the db to override the default sort order), but most of the items just sort by id.

You will need to redefine the method thusly:
public static dbObject[] GetAsArray(HashMap<Long, ? extends dbObject> map) {
Collection<? extends dbObject> list = map.values();
dbObject[] ar = list.toArray(new dbObject[] {});
Arrays.sort(ar);
return ar;
}
A Map<Long, dbEmployee> cannot be used in place of a Map<Long, dbObject>, because although it has some of the same behaviour, some of its behaviour is very different. In particular, you can't add an Object of type dbObject to a Map<Long, dbEmployee>.
If the method GetAsArray(HashMap<Long, dbObject> map) allowed you to pass it a Map<Long, dbEmployee>, you would be able to add dbObjects to the map from inside the method. The method has no way to know that the map is not actually a map of dbObjects. Then, if you held on to a reference to the map outside of the method, you would have big problems. The map would no longer by type-safe. It would say it was a Map<Long, dbEmployee>, but it would actually contain dbObjects that were not dbEmployees.
The ? extends dbObject syntax allows you to specify what you can get out of the map without detailing what can go in it. You'll notice that if you now try to add something to the map inside the GetAsArray(HashMap<Long, extends dbObject> map) method, you'll get a compile error.
(There is an equivalent syntax, ? super dbEmployee, that would let you put things in the map without knowing what could come out).

Related

transform Collection<myClass> to Collection<String>

I trying to implement functionally similar to CollectionUtils transform (Apache Commons Collections)
class CollectionUtils {
public static void transformerModifier(Collection<MyClass> myCollection) {
// How should I implement this method in order that
// output from the line 1 and line 2 will be the same ?
}
public static List<String> transform(Collection<MyClass> myCollection) {
List<String> strCollection = new LinkedList<>();
for (MyClass item : myCollection) {
strCollection.add(item.getName());
}
return strCollection;
}
}
class myClass {
private String name;
private int value;
myClass( String name, int value) {
this.name = name ;
this.value = value;
}
public String toString(){
return new String(name+ ":" + value ) ;
}
}
class MyClassCollection{
private List<myClass> list ;
myClassCollection(List<myClass> list){
this.list = list;
}
List<myClass> collection(){
return list.clone();
}
}
public class TestClass{
public static void main (String[] args) {
List<MyClass> list = new ArrayList<>();
list.add(new myClass("John", 12);
list.add(new myClass("Mike", 16);
list.add(new myClass("Eric", 13);
list.add(new myClass("Mark", 142);
list.add(new myClass("Alex", 112);
MyClassCollection myOjb = new MyClassCollection(list );
CollectionUtils.transformerModifier(myObj.collection() );
List<MyClass> myList = CollectionUtils.transform(myObj.collection());
System.out.println(Arrays.toString(myObj.collection().toArray)); // line 1
System.out.println(Arrays.toString(myList.toArray)); // line 2
}
}
output: [John,Mike,Eric,Mark,Alex] // output after line 1
output: [John,Mike,Eric,Mark,Alex] // should be output after line 2
My question is it possible to implement method transformerModifier in the way that it will change collection of the object myObj so that myObj.collection() return not the List<myClass> but the List of List<String> ( where string is the data from private String name data member of myClass ) ?
My guess is that the solution should be through anonymous class. However, I didn't understand yet how should I implement it.
If you are using Java 8, you could make use of streams and map() to do something like this:
List<MyClass> myClassList = new ArrayList<>();
//add your items to myClassList here
List<String> names = myClassList.stream().map(MyClass::getName).collect(Collectors.toList());
//names will now consist of a List of all the names associated with
//each of the MyClass objects within myClassList in the same order
This solution makes use of Method Reference as well MyClass::getName. This calls the getName method on each object in the stream mapping it to its respective spot in the transformed stream using .map().
Next it uses .collect() to bring it back from a stream to a list using Collectors.toList().
If you are working with a lot of objects within myClassList, this process can be sped up using .parallelStream() instead of .stream(), but if you are not working with a large amount of data, you may see a reduction in performance with .parallelStream(). It all depends on how many objects you expect to be present within the List.
public interface Converter<I, O> {
void tranformer(List list);
O retriever(I obj);
}
_
public static <I, O> void transform(Converter<I, O> converter, List inputList) {
Iterator<I> it = inputList.iterator();
List list = new LinkedList<>();
while (it.hasNext()) {
list.add(converter.retriever(it.next()));
}
converter.tranformer(list);
}
_
public static void main(String[] args) {
List<MyClass> list = new ArrayList<>();
list.add(new myClass("John", 12);
list.add(new myClass("Mike", 16);
list.add(new myClass("Eric", 13);
list.add(new myClass("Mark", 142);
list.add(new myClass("Alex", 112);
MyClassCollection myclasscollection = new MyClassCollection(list);
final List collectionList = myclasscollection.collection();
CollectionUtils.transform(new Converter<myClass, String>() {
#Override
public void tranformer(List list) {
employeeList.clear();
employeeList.addAll(list);
}
#Override
public String retriever(myClass obj) {
return obj.name; // make the data member public or add getter
}
}, collectionList);
collectionList.get(0).toString.toLowerCase();
}
This isn't fully what you need but I bet this isn't bad alternative. Please, notice that could output collection collectionList will be collection of objects ( not String ), however, you can access to methods of the String data type just to right like this collectionList.get(0).toString.toLowerCase(); Hope this help.

Instantiating DynamoDBQueryExpression with generic classtypes

Edit: I was trying to simplify my problem at hand a little, but turns out, it created more confusion instead. Here's the real deal:
I am working with AWS's Java SDK for DynamoDB. Using the DynamoDBMapper class, I am trying to query DynamoDB to retrieve items from a particular table. I have several objects that map to my DynamoDB tables, and I was hoping to have a generic method that could accept the mapped objects, query the table, and return the item result.
Psudo-code:
#DynamoDBTable(tableName="testTable")
public class DBObject {
private String hashKey;
private String attribute1;
#DynamoDBHashKey(attributeName="hashKey")
public String getHashKey() { return this.hashKey; }
public void setHashKey(String hashKey)
#DynamoDBAttribute(attributeName="attribute1")
public String getAttribute1() { return this.attribute1; }
public void setAttribute1(String attribute1) { this.attribute1 = attribute1; }
}
public class DatabaseRetrieval {
public DatabaseRetrieval()
{
DBObject dbObject = new DBObject();
dbObject.setHashKey = "12345";
DBRetrievalAgent agent = new DBRetrievalAgent;
dbObject = agent.retrieveDBObject(dbObject.getClass(), dbObject);
}
}
public class DBRetrievalAgent {
public Object retrieveDBObject(Class<?> classType, Object dbObject)
{
DynamoDBQueryExpression<classType> temp = new DynamoDBQueryExpression<classType>().withHashKeyValues(dbObject);
return this.dynamoDBMapper.query(classType, temp);
}
}
Use a type witness within your method:
public <T> String getResult(Class<T> type) {
List<T> newList = new ArrayList<>();
//other code
}
Try this
ArrayList<T> newList = new ArrayList<>();
You can specify the type as T for your getResult() to make it generic (i.e., accepts any class) as shown below:
public <T> String getResult(T t) {
String result = "";
List<T> newList = new ArrayList<>();
// perform actions
return result;
}

Sorting a collection in a generic method in Java 8

The following method performs ordering.
public List<Comparator<Entity>> sort(Map<String, String> map) {
List<Comparator<Entity>> list = new ArrayList<Comparator<Entity>>();
for (Map.Entry<String, String> entry : map.entrySet()) {
boolean sortOrder = entry.getValue().equalsIgnoreCase("asc");
switch (entry.getKey()) {
case "id":
list.add(sortOrder ? Comparator.comparing(Entity::getId) : Comparator.comparing(Entity::getId, Comparator.reverseOrder()));
break;
case "size":
list.add(sortOrder ? Comparator.comparing(Entity::getSize) : Comparator.comparing(Entity::getSize, Comparator.reverseOrder()));
//break;
}
}
return list;
}
The list being returned by the above method is used in the following way.
// map is initialized somewhere based on client's interactions with sorting.
// Based on client's interactions, map may be empty or it may contain one or more ordering fields.
if (MapUtils.isNotEmpty(map)) { // map = new LinkedHashMap<String, String>();
List<Comparator<Entity>> comparators = sort(map);
Comparator<Entity> comparator = comparators.remove(0);
for (Comparator<Entity> c : comparators) {
comparator = comparator.thenComparing(c);
}
list = list.stream().sorted(comparator).collect(Collectors.toList());
} else {
// This is the default ordering.
list = list.stream().sorted(Comparator.comparing(Entity::getId).reversed()).collect(Collectors.toList());
}
Entity contains two fields named id of type Integer and size of type BigDecimal and list is a type of List<Entity>.
Since there are several other classes having the same fields with the same datatypes, I want this method to be generic so that it has to be defined only once like so,
public <T extends Object> List<Comparator<T>> sort(Map<String, String> map, Class<T> clazz) {
List<Comparator<T>> list = new ArrayList<Comparator<T>>();
// Sorting logic.
return list;
}
But doing so, expressions like T::getId will not compile as obvious, since the generic type parameter T evaluates to Object.
Is there a way to code sorting without knowing the actual class type so that this method can be prevented from being repeated everywhere, when it is needed?
A simple way, without having to rely on reflection magic, is to introduce a common interface for all the types having the same fields with the same datatypes as Entity.
Consider the following IdSize interface with the following Entity.
interface IdSize {
Integer getId();
BigDecimal getSize();
}
class Entity implements IdSize {
private Integer id;
private BigDecimal size;
#Override
public Integer getId() {
return id;
}
#Override
public BigDecimal getSize() {
return size;
}
}
Then you can make your method generic like this:
public <T extends IdSize> List<Comparator<T>> sort(Map<String, String> map) {
List<Comparator<T>> list = new ArrayList<Comparator<T>>();
for (Map.Entry<String, String> entry : map.entrySet()) {
boolean sortOrder = entry.getValue().equalsIgnoreCase("asc");
Comparator<T> comparator = null;
switch (entry.getKey()) {
case "id":
comparator = Comparator.comparing(IdSize::getId);
break;
case "size":
comparator = Comparator.comparing(IdSize::getSize);
break;
default: // do something here, throw an exception?
}
list.add(sortOrder ? comparator : comparator.reversed());
}
return list;
}
(I refactored a little the switch-case statement to remove the duplicated code.). Also, you might want to add a default clause.
Use interfaces:
public interface Sizable {
BigDecimal getSize();
}
public interface Id {
int getId();
}
Have your classes implement those interface and use them in your generic methods:
public <T extends Id & Sizable> List<Comparator<T>> sort(Map<String, String> map) {
// ...
}
You'll probably need something more dynamic. Some annotations may help
class Shoe
#Column("id")
#Sortable
public int getId(){ ... }
#Column("Description")
public String getDescription(){...}
Given any class, you can reflect on columns to display, columns that can be sorted ("id", ...), and values of columns ("getId()", ...).
If you want to create a compound Comparator anyway, there is no point in filling a List first. Just do it in one operation:
public static <T> Comparator<T> getOrdering(
Map<String, String> map, Map<String,Comparator<T>> defined) {
return map.entrySet().stream().map(e -> {
Comparator<T> c=defined.get(e.getKey());
return e.getValue().equalsIgnoreCase("asc")? c: c.reversed();
})
.reduce(Comparator::thenComparing)
.orElseThrow(()->new IllegalArgumentException("empty"));
}
This works for arbitrary types but requires to provide a map of existing comparators for a type. But this map isn’t a restriction, it actually improves the operation as it removes the hardcoded set of existing named property comparators. You can use it with an arbitrary type, Entity being exemplary here, as follows:
Map<String,Comparator<Entity>> map=new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
map.put("id", Comparator.comparing(Entity::getID));
map.put("size", Comparator.comparing(Entity::getSize));
Comparator<Entity> cmp=getOrdering(param, map);
whereas param is the ordered map of your question, mapping from property name to either "asc" or "desc". The map holding the predefined comparators can be created once in initialization code and then be re-used.
The creation code doesn’t look so complicated that it deserves implementing a dynamic solution, however, if you still wish to do it, here is the code to generate such a map for arbitrary classes:
public final class DynamicComparators<T> {
public static <T> Map<String,Comparator<T>> getComparators(Class<T> cl) {
return CACHE.get(cl).cast(cl).comps;
}
private static final ClassValue<DynamicComparators> CACHE
=new ClassValue<DynamicComparators>() {
#Override protected DynamicComparators computeValue(Class<?> type) {
return new DynamicComparators<>(type);
}
};
private final Class<T> theClass;
private final Map<String, Comparator<T>> comps;
private DynamicComparators(Class<T> cl) {
theClass=cl;
Map<String,Comparator<T>> map=new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
try {
BeanInfo bi=Introspector.getBeanInfo(cl);
MethodHandles.Lookup l=MethodHandles.lookup();
MethodType invoked=MethodType.methodType(Function.class);
for(PropertyDescriptor pd: bi.getPropertyDescriptors()) {
Method m=pd.getReadMethod();
if(m==null) continue;
Class<?> t=m.getReturnType();
if(!t.isPrimitive() && !Comparable.class.isAssignableFrom(t))
continue;
MethodHandle mh=l.unreflect(m);
MethodType mt=mh.type();
#SuppressWarnings("unchecked")Comparator<T> cmp
= Comparator.comparing((Function<T,Comparable>)LambdaMetafactory
.metafactory(l, "apply", invoked, mt.generic(), mh, mt)
.getTarget().invokeExact());
map.put(pd.getName(), cmp);
}
} catch(Throwable ex) {
throw new RuntimeException(ex);
}
this.comps=Collections.unmodifiableMap(map);
}
#SuppressWarnings("unchecked") <U> DynamicComparators<U> cast(Class<U> cl) {
if(cl!=theClass) throw new ClassCastException();
return (DynamicComparators<U>)this;
}
}

Need to loop over an array/list/whatever and *return to caller* each element -but the loop only runs once, of course

I'm obviously missing something here, as this sound basic enough but yet...
I have a collection of objects . I need to use each one of them as parameter in constructor for a new object and return each new object to the caller method, one by one.
But -if I loop over the collection obviously the loop only runs once, and only returns the 1st object.
Edit : Returning the whole collection or some new collection will not work because :
The caller method [not mine to change] runs inside a start() method of a Runnable ThingProvider, which returns a single Thing whenever a request is submitted to it. So, returning List is not possible.
Thanks :)
public List<T> loop(Collection<? extends U> coll) {
List<T> a = new ArrayList<T>();
for (U u : coll){
a.add(new T(u));
}
return a;
}
Return a custom Iterator. Assumming your new objects are of class MyObject and the constructor accepts an Object:
public Iterator<MyObject> myObjectsIterator(final Iterator<? extends Object> it) {
return new Iterator<MyObject>() {
public boolean hasNext() {
return it.hasNext();
}
public MyObject next() {
return new MyObject(it.next());
}
public void remove() {
it.remove();
}
};
}
And you would call it like this:
...
Iterator<MyObject> myIt = myObjectsIterator(myListOfObjects.iterator());
// Now you can pass myIt around as a normal object. It will remember
// which one is the next Object with which to construct a MyObject
// and will generate it on the fly
...
while (myIt.hasNext()) { // is there any MyObject remaining?
MyObject myObj = myIt.next(); // gets the next MyObject
// do something with myObj
}
...
This is a poorly worded question and I think as others have noted, just returning a new list of the objects is fine. But if you really want to process them one at a time while you're looping through it, you can use the command pattern.
public interface Command {
void execute(NewType object);
}
Now in your caller method, you can do the following:
public void doSomething() {
processList(myList, new Command() {
void execute(NewType object) {
// Do whatever you want with this object
}
});
}
And, in the method that will actually go through the list:
public void processList(Iterable<OldType> values, Command command) {
for(OldType v : values) {
NewType newType = new NewType(v);
command.execute(newType);
}
}
In java you can return only once. So if you want to get some informations from your methods either you wrap them into a "Big" Object (here a List) or you give to the method the means to put informations in your parameters.
You could have something like this :
public static void main(String... args){
List<Parameter> parameters = methodToGetParameters();
List<Result> results = generateObjectsFromList(parameters);
for(Result result : results){
handleAResult(result);
}
}
public List<Result> generateObjectsFromList(List<Parameter> parameters){
List<Result> results = new ArrayList<Result>();
for(Parameter parameter : parameters){
results.add(new Result(parameter));
}
return results;
}
Or like this :
public static void main(String... args){
List<Parameter> parameters = methodToGetParameters();
List<Result> results = new ArrayList<Result>();
generateObjectsFromList(parameters, results);
for(Result result : results){
handleAResult(result);
}
}
public void generateObjectsFromList(List<Parameter> parameters, List<Result> results){
for(Parameter parameter : parameters){
results.add(new Result(parameter));
}
}
A third way to do this would be to use fields, but it's not really good to have a lot of fields if they're not really used (or only by one method).
On the same topic :
Java Object Oriented Design Question: Returning multiple objects in java(Updated)
Using a java method to return multiple values?
Return a collection from the method and in the collection implement a custom iterator to transform the input collection to the new collection. The following code shows how to do it using the Google Guava library:
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
public class Test {
static class Person {
public final String name;
public Person(String name) {
this.name = name;
}
}
public static Collection<Person> peopleFromNames(Collection<String> names) {
return Collections2.transform(names, new Function<String, Person>() {
public Person apply(String name) {
return new Person(name);
}});
}
public static void main(String[] args) {
List<String> names = Arrays.asList("Brian", "Albert", "Roger");
for (Person person : peopleFromNames(names)) {
System.out.println(person.name);
}
}
}
do you mean using of delegates something like below
public class Test {
private static class Person{
private final String name;
Person(String name){
this.name = name;
}
#Override
public String toString() {
return return name;
}
}
private interface Printer {
void print(Object object);
}
public static void main(String[] args) {
final String[] names = {"one", "two", "three"};
final ArrayList<Person> people = construct(names, new Printer() {
#Override
public void print(Object object) {
System.out.println(object.toString());
}
});
}
private static ArrayList<Person> construct(String[] names, Printer printer) {
ArrayList<Person> people = new ArrayList<Person>();
for (String name : names) {
printer.print(new Person(name));
}
return people;
}
}
It's Possible.
Check these Project for Java-yield , yield4Java, infomancers
If you're using this just once in your entire code, You're better off choosing a method from the other answers.
Return a list of the new objects.

Converting lists of one element type to a list of another type

I'm writing an adapter framework where I need to convert a list of objects from one class to another. I can iterate through the source list to do this as in
Java: Best way of converting List<Integer> to List<String>
However, I'm wondering if there is a way to do this on the fly when the target list is being iterated, so I don't have to iterate through the list twice.
Java 8 way:
List<String> original = ...;
List<Wrapper> converted = original.stream().map(Wrapper::new).collect(Collectors.toList());
assuming Wrapper class has a constructor accepting a String.
My answer to that question applies to your case:
import com.google.common.collect.Lists;
import com.google.common.base.Functions
List<Integer> integers = Arrays.asList(1, 2, 3, 4);
List<String> strings = Lists.transform(integers, Functions.toStringFunction());
The transformed list is a view on the original collection, so the transformation happens when the destination List is accessed.
As an alternative to the iterator pattern, you can use a abstract generic mapper class, and only override the transform method:
create a generic collection mapper for any data type
[optional] create a library of methods that transform between different data types (and override the method)
use that library
the implementation:
// Generic class to transform collections
public abstract class CollectionTransformer<E, F> {
abstract F transform(E e);
public List<F> transform(List<E> list) {
List<F> newList = new ArrayList<F>();
for (E e : list) {
newList.add(transform(e));
}
return newList;
}
}
// Method that transform Integer to String
// this override the transform method to specify the transformation
public static List<String> mapIntegerToStringCollection(List<Integer> list) {
CollectionTransformer transformer = new CollectionTransformer<Integer, String>() {
#Override
String transform(Integer e) {
return e.toString();
}
};
return transformer.transform(list);
}
// Example Usage
List<Integer> integers = Arrays.asList(1,2);
List<String> strings = mapIntegerToStringCollection(integers);
This would be useful is you have to use transformations every time, encapsulating the process.
So you can make a library of collection mappers very easy.
If you are trying to get a list of elements within a list then use the below code.Here the list of objects contains attribute name and below gets you list of names from that list
inputList.stream().map(p -> p.getName()).collect(Collectors.toList());
You can write a mapping iterator that decorates an existing iterator and applies a function on it. In this case, the function transforms the objects from one type to another "on-the-fly".
Something like this:
import java.util.*;
abstract class Transformer<T, U> implements Iterable<U>, Iterator<U> {
public abstract U apply(T object);
final Iterator<T> source;
Transformer(Iterable<T> source) { this.source = source.iterator(); }
#Override public boolean hasNext() { return source.hasNext(); }
#Override public U next() { return apply(source.next()); }
#Override public void remove() { source.remove(); }
public Iterator<U> iterator() { return this; }
}
public class TransformingIterator {
public static void main(String args[]) {
List<String> list = Arrays.asList("1", "2", "3");
Iterable<Integer> it = new Transformer<String, Integer>(list) {
#Override public Integer apply(String s) {
return Integer.parseInt(s);
}
};
for (int i : it) {
System.out.println(i);
}
}
}
Lambdaj allows to do that in a very simple and readable way. For example, supposing you have a list of Integer and you want to convert them in the corresponding String representation you could write something like that;
List<Integer> ints = asList(1, 2, 3, 4);
Iterator<String> stringIterator = convertIterator(ints, new Converter<Integer, String> {
public String convert(Integer i) { return Integer.toString(i); }
});
Lambdaj applies the conversion function only while you're iterating on the result.
There is also a more concise way to use the same feature. The next example works supposing that you have a list of persons with a name property and you want to convert that list in an iterator of person's names.
Iterator<String> namesIterator = convertIterator(persons, on(Person.class).getName());
Pretty easy. Isn't it?
This Could be a solutions --> by using map
List<Employee> employee = Arrays.asList(new Emp(1, 100), new Emp(2, 200), new Emp(3, 300));
List<Employee> employeS = employee.stream()
.map(emp -> new Emp(emp.getId(), emp.getSalary * 100))
.collect(Collectors.toList());
employeS .stream() .forEach(s -> System.out.println("Id :" + s.getId() + " Salary :" + s.getSalary()));
That question does not iterate through the list twice. It just iterates once and by far is the only known method.
Also you could use some transformer classes in commons-collections of google-collections but they all do the same thing under the hood :) the following being one way
CollectionUtils.collect(collectionOfIntegers, new org.apache.commons.collections.functors.StringValueTransformer());
Well, you could create your own iterator wrapper class to do this. But I doubt that you would save much by doing this.
Here's a simple example that wraps any iterator to a String iterator, using Object.toString() to do the mapping.
public MyIterator implements Iterator<String> {
private Iterator<? extends Object> it;
public MyIterator(Iterator<? extends Object> it) {
this.it = it;
}
public boolean hasNext() {
return it.hasNext();
}
public String next() {
return it.next().toString();
}
public void remove() {
it.remove();
}
}
I think you would either have to create a custom List (implementing the List interface) or a custom Iterator. For example:
ArrayList<String> targetList = new ArrayList<String>();
ConvertingIterator<String> iterator = new ConvertingIterator<String>(targetList);
// and here you would have to use a custom List implementation as a source List
// using the Iterator created above
But I doubt that this approach would save you much.
Here's an on-the-fly approach. (There must be something already like this in the jdk; I just can't find it.)
package com.gnahraf.util;
import java.util.AbstractList;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
/**
*
*/
public class Lists {
private Lists() { }
public static <U,V> List<V> transform(List<U> source, Function<U, V> mapper) {
return new ListView<U, V>(source, mapper);
}
protected static class ListView<U, V> extends AbstractList<V> {
private final List<U> source;
private final Function<U, V> mapper;
protected ListView(List<U> source, Function<U, V> mapper) {
this.source = Objects.requireNonNull(source, "source");
this.mapper = Objects.requireNonNull(mapper, "mapper");
}
#Override
public V get(int index) {
return mapper.apply(source.get(index));
}
#Override
public int size() {
return source.size();
}
}
}

Categories