There are a couple of Listeners L1, L2, ... all similar:
interface L1 { void onL1(); }
interface L2 { void onL2(); }
...
All are used in class EventMaker like this:
class EventMaker {
...
List<L1> l1s = new LinkedList<>();
List<L2> l2s = new LinkedList<>();
...
void addL1(L1 l1) {...; l1s.add(l1); ...;}
void removeL1(L1 l1) {...; l1s.remove(l1); ...;}
void callL1() {...}
void addL2(L2 l2) {l2s.add(l2);}
void removeL2(L2 l2) {l2s.remove(l2);}
void callL2() {...}
...
}
What can I do, to reduce the repeating code? I tried to use generic methods, but it is no solution in many ways.
// ************************************************************************
My Solution:
abstract class Caller<Listener> {
List<Listener> listeners;
public Caller() {
listeners = new LinkedList<>();
}
public void add(Listener listener) {
listeners.add(listener);
}
public void remove(Listener listener) {
listeners.remove(listener);
}
public void call() {
for (Listener listener : listeners) {
onCall(listener);
}
}
public abstract void onCall(Listener listener);
}
Empty Listener-Interface:
interface Listener {
}
For Every-Listener:
class L1Caller extends Caller<L1> {
#Override
public void onCall(L1 listener) {
listener.l1(); // unique name
}
}
Finally I add for every listern-type a caller to my main-class.
...
L1Caller l1Caller;
L2Caller l2Caller;
...
And use it like:
l1Caller.add(...);
l2Caller.call();
I don't know if this is best practice, but it's certainly possible.
public class Caller {
public static final Token<L1> L1 = new Token<>();
public static final Token<L2> L2 = new Token<>();
public static class Token<T> {
// Making the constructor private means that no other Tokens can be made.
private Token() {}
}
private final Map<Token<?>, List<Object>> lists;
public Caller() {
lists = new HashMap<>();
Token<?>[] tokens = {L1, L2};
for (Token<?> token : tokens)
lists.put(token, new LinkedList<>());
}
public <T> void add(Token<T> token, T t) {
lists.get(token).add(t);
}
public <T> void remove(Token<T> token, T t) {
lists.get(token).remove(t);
}
}
Despite the use of wildcards and Object, it's completely type-safe and is easy to use:
caller.add(Caller.L1, () -> {
// do stuff
});
Use the existing ChangeListener with its ChangeEvent where the source is of interest. Alterative use generic types.
Then make a class to hold a list of listeners, say
public class ChangeManager {
private final List listeners = ...
public void addChangeListener(ChangeListener listener) { ... }
public void notifyChange(ChangeEvent event) { ... }
}
This can handle listeners in a garbage collected and concurrency safe way.
Now your class delegates to several ChangeManagers.
private final ChangeManager l1 = new ChangeManager();
private final ChangeManager l2 = new ChangeManager();
private final ChangeEvent L1_EVENT = new ChangeEvent(this);
...
l1.addChangeListener(changeEvent -> {
...
});
l1.notifyChange(L1_EVENT);
You should retain the individual add* methods to your API because they are meaningful and makes for a clearer API. One option which alters your API is to have a single add(type, listener) and route all invocations through it. However, then you must expose that type and the client must coordinate on adding the right listener to the right type.
One way to not alter your API but internally manage the listeners in aggregate is a pattern like this:
class EventMaker {
...
static String TYPE_L1 = "L1";
static String TYPE_L2 = "L2";
Map<String, List<Object>> listeners;
...
void addInternal(String t, Object listener) {
List<Object> list = listeners.get(t);
if (list == null) { list = new CopyOnWriteArrayList<>(); listeners.put(t, list); }
list.add(listener);
}
void removeInternal(String t, Object listener) {
List<Object> list = listeners.get(t);
if (list != null) { list.remove(listener; }
// optional
if (list != null && list.isEmpty) listeners.remove(t);
}
<ListenerType> List<ListenerType> getInternal(String t, Class<ListenerType> cls) {
List<Object> list = listeners.get(t);
if (list == null) return Collections.emptyList();
return (List<ListenerType>)list;
}
void removeInternal(String t, Object listener) {...}
void addL1(L1 l1) { addInternal(TYPE_L1, l1);}
void removeL1(L1 l1) { removeInternal(TYPE_L1, l1);}
void callL1() {
List<L1> list = getInternal(TYPE_L1, L1.class);
for (L1 ears : list) ears.onL1();
}
void addL2(L2 l2) {addInternal(TYPE_L2, l2);}
void removeL2(L2 l2) {removeInternal(TYPE_L2, l2);}
void callL2() {...}
...
}
The type is ignored in the map since you are protecting everything in and out, and safely cast when accessing one of the listener lists. The type is still necessary when notifying your listeners though since they have no common base. The concurrent-safe CopyOnWriteArrayList also has some performance implications worth looking into for listener lists.
I would also recommend returning a handle instead of requiring a removeListener call. This allows the caller to not have to look up the event source when cleaning up, but has an OO handle that does the work. java.lang.AutoCloseable (if using Java 7 or later, else java.lang.Runnable) is a good choice for this:
AutoCloseable addInternal(String t, final Object listener) {
List<Object> list = listeners.get(t);
if (list == null) { list = new ArrayList<>(); listeners.put(t, list); }
list.add(listener);
final List<Object> flist = list; // for final reference below
return new AutoCloseable() {
public void close() { flist.remove(listener); }
};
}
And now the caller operates by simply calling .close() on that returned handle to unregister.
And a simpler handle if you are using Java 8:
AutoCloseable addInternal(String t, final Object listener) {
List<Object> list = listeners.get(t);
if (list == null) { list = new ArrayList<>(); listeners.put(t, list); }
list.add(listener);
return () -> list.remove(listener);
}
You also should look into properly synchronizing to ensure thread-safety if it is a concern, making your fields private and final as appropriate, and other good-practice cleanup I did not address in those examples.
Related
I'm currently trying to hit a service and get returned a list of objects, before it gets returned to the subscriber, I want to make another synchronous call for each object in the list to make another service call to set a missing field. I'm successfully having all calls being made, but the object returned in the subscriber has this field I need to have set to null. Here is an example of my code:
Example Service:
rx.Observable<List<ExampleObject>> getExampleObject();
rx.Observable<MissingObject> getMissingObjectByFoo(#Path("foo") String foo);
Example Class:
public class ExampleObject {
String foo;
MissingObject bar;
public String getFoo() {
return this.foo;
}
public void setFoo(String value) {
this.foo = value;
}
public MissingObject getBar() {
return this.bar;
}
public void setBar(MissingObject value) {
this.bar = value;
}
}
Example Implementation:
mService.getExampleObject().flatMap(new Func1<List<ExampleObject>, Observable<?>>() {
#Override
public Observable<List<ExampleObject>> call(List<ExampleObject> exampleObjects) {
for (ExampleObject entry : exampleObjects) {
String foo = entry.getFoo();
mService.getMissingObjectByFoo(foo)
.subscribeOn(mScheduler.backgroundThread())
.observeOn(mScheduler.mainThread())
.subscribe(new Subscriber<MissingObject>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
}
#Override
public void onNext(MissingObject missingObject) {
entry.setBar(missingObject);
}
});
}
return Observable.just(exampleObjects);
};
Because your intermediary call to update the entry is asynchronous, I don't think you can stick to using a List<ExampleObject>, but should instead manipulate ExampleObject directly from the Observable:
mService.getExampleObject()
// Spread the list
.flatMap(list -> Observable.from(list))
// Update your object
// Here we zip the object with the missing object,
// so that when the missing object is obtained,
// we update the entry and emit it.
.flatMap(entry -> Observable.zip(
Observable.just(entry),
mDocsService.getMissingObjectByFoo(entry.getFoo()),
(entry, missingObject) -> {
entry.setBar(missingObject);
return entry;
})
)
// if you really want a map after all
.toList();
Side note:
You can skip the zip if you are fine with having the function in the map depend on an external variable (the entry). That's something I try to avoid, but here it is anyway:
.flatMap(entry -> mDocsService.getMissingObjectByFoo(entry.getFoo())
.map(missingObject -> {
entry.setBar(missingObject);
return entry;
})
)
You're looking for the zip operator, as described here: Zip Operator. I think you want to flatmap to a zip of all of your calls, so, something like this:
mService.getExampleObject().flatMap(new Func1<List<ExampleObject>, Observable<ExampleObject>>() {
#Override
public Observable<List<ExampleObject>> call(List<ExampleObject> exampleObjects) {
List<Observable<ExampleObject>> allTheObservables = new ArrayList<Observable<ExampleObject>>();
for (ExampleObject entry : exampleObjects) {
allTheObservables.add(mService.getMissingObjectByFoo(foo).map(new Func1<MissingObject, ExampleObject>() {
#Override
public ExampleObject call(MissingObject missingObject) {
return entry.setBar(missingObject);
}
}));
}
return Observable.zip(allTheObservables, new FuncN<ExampleObject>() {
#Override
public ExampleObject call(ExampleObject... args) {
return Arrays.asList(args);
}
});
}
});
and in case that doesn't work, or there are syntax issues, here's a concrete example, using the github api:
service.getContributorsObservable("square", "dagger")
.flatMap(new Func1<List<Contributor>, Observable<List<String>>>() {
#Override
public Observable<List<String>> call(List<Contributor> contributors) {
List<Observable<String>> allTheObservables = new ArrayList<>(contributors.size());
for (final Contributor contributor : contributors) {
allTheObservables.add(service.getContributorsObservable(contributor.login).map(new Func1<User, String>() {
#Override
public String call(User user) {
return contributor.login + " is " + user.name;
}
}));
}
return Observable.zip(allTheObservables, new FuncN<List<String>>() {
#Override
public List<String> call(Object... args) {
return Arrays.asList((String[]) args);
}
});
}
});
Keep in mind that this will make n+1 network calls, 1 for the list of ExampleObjects, and then 1 per ExampleObject in that list. If it is at all possible, I strongly suggest that you speak with the maintainer of the API to get the information lookup taken care of on the API side. Just know that this is going to use some bandwidth!
I built a generic cache that fetches values on miss by delegating to a ValueGenerator component. Internally, it has a map for values it has already obtained, and another map for in-flight requests so that they can be re-used across subscribers.
Here's the simplified code before I attempt to make it thread safe. My questions will follow.
public class NetworkCache<K, V> {
private final Map<K, V> mValues;
private final Map<K, Observable<V>> mRequests;
private final ValueGenerator<K, V> mValueGenerator;
public NetworkCache(ValueGenerator<K, V> valueGenerator) {
mValues = new HashMap<>();
mRequests = new HashMap<>();
mValueGenerator = valueGenerator;
}
public Observable<V> get(final K key) {
V value = mValues.get(key);
if (value != null) {
// We already had the value
return Observable.just(value);
}
Observable<V> requestObservable = mRequests.get(key);
if (requestObservable == null) {
// New request to fetch the value
requestObservable = mValueGenerator.generate(key);
// Store in-flight request for potential re-use
mRequests.put(key, requestObservable);
requestObservable.subscribe(new Subscriber<V>() {
#Override
public void onCompleted() { mRequests.remove(key); }
#Override
public void onError(Throwable e) { mRequests.remove(key); }
#Override
public void onNext(V value) { mValues.put(key, value); }
});
}
return requestObservable;
}
public interface ValueGenerator<K, V> {
Observable<V> generate(K key);
}
}
Now I'm trying to think how this could break under concurrency scenarios. I believe the focus should be on those two Map that are queried in get(), and modified in the subscribe callback.
I think it's reasonable to assume/enforce that this class can only be called on the main thread. The ValueGenerator, however, should be able to schedule its work on a different thread, as my use case is actually network requests.
I see 3 options, and I'd like help to figure out which one to use.
1. Use ConcurrentHashMap instead of HashMap
Constructor would change to:
public NetworkCache(ValueGenerator<K, V> valueGenerator) {
mValues = new ConcurrentHashMap<>();
mRequests = new ConcurrentHashMap<>();
mValueGenerator = valueGenerator;
}
With this approach, I don't know if it is sufficient and/or overkill.
2. Observe ValueGenerator call on main thread
To me, this means that all map operations would happen on the main thread (assuming that NetworkCache is only used there), even if the ValueGenerator used subscribeOn(Schedulers.io()). This would mean it is thread safe.
if (requestObservable == null) {
// New request to fetch the value
requestObservable = mValueGenerator
.generate(key)
.observeOn(AndroidSchedulers.mainThread());
...
3. Synchronize every access to the maps
I would keep using HashMap and the get method would become the following. Here, is synchronizing on the maps themselves the right approach? Do I need to block on every operation, or just put & remove?
public Observable<V> get(final K key) {
V value;
synchronized (mValues) {
value = mValues.get(key);
}
if (value != null) {
return Observable.just(value);
}
Observable<V> requestObservable;
synchronized (mRequests) {
requestObservable = mRequests.get(key);
}
if (requestObservable == null) {
requestObservable = mValueGenerator.generate(key);
synchronized (mRequests) {
mRequests.put(key, requestObservable);
}
requestObservable.subscribe(new Subscriber<V>() {
#Override
public void onCompleted() {
synchronized (mRequests) {
mRequests.remove(key);
}
}
#Override
public void onError(Throwable e) {
synchronized (mRequests) {
mRequests.remove(key);
}
}
#Override
public void onNext(V value) {
synchronized (mValues) {
mValues.put(key, value);
}
}
});
}
return requestObservable;
}
A little background on the utilization: the cache's get method would be called in rapid succession 1-10 times for different keys. That event would be infrequent, but could happen within a few seconds. It's when the second series of calls arrives, mixed with the observables from the first series coming back, that I worry about the execution.
I would do this with a single ConcurrentMap and AsyncSubject:
public class RequestCache<K, V> {
final ConcurrentMap<K, AsyncSubject<V>> values;
final Function<? super K, ? extends Observable<? extends V>> valueGenerator;
public RequestCache(
Function<? super K, ? extends Observable<? extends V>> valueGenerator) {
this.values = new ConcurrentHashMap<>();
this.valueGenerator = valueGenerator;
}
public Observable<V> get(K key) {
AsyncSubject<V> result = values.get(key);
if (result == null) {
result = AsyncSubject.create();
AsyncSubject<V> current = values.putIfAbsent(key, result);
if (current == null) {
Observable<? extends V> source = valueGenerator.apply(key);
source.subscribe(result);
} else {
result = current;
}
}
return result;
}
}
This is fully threadsafe and calls valueGenerator once per key only.
I think you should synchronize whole getter and setter functions.
In a system, I have many in-memory objects processing data. And I have to monitor all required objects. And if these objects crossing their thresholds user must notify for this incident. So I am thinking for creating a WatcherService for this. And any required objects must have to register for this. Here is the skeleton of my thinking.
class Foo {
private Integer a;
private String b;
private Long c;
private List<ASD> asds;
//setter and getter
}
class Bar {
private Integer aa;
private Integer ab;
private Float cc;
//setter and getter
}
class WatchThread<T> implements Runnable, IWatchThread { // Actually IWatchThread extends Runnable
private final T t;
private final Set<String> paramsToWatch;
private Boolean isRunning = false;
public WatchThread(T t, Set<String> paramsToWatch) {
this.t = t;
this.paramsToWatch = paramsToWatch;
}
public void run() {
while(isRunning) {
//Do some comparsion work by Reflection !!??!!
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class WatcherService {
private static final Map<Object, IWatchThread> watchThreads = new HashMap<>();
public static <T> void registerForWatch(T t, Object keyToMaintain, Set<String> paramsToWatch) {
IWatchThread watchThread = new WatchThread<T>(objectValue, paramsToWatch);
watchThread.setIsRunning = true;
watchThread.start();
watchThreads.put(keyToMaintain, watchThread);
}
public static unregister(Object keyToMaintain) {
IWatchThread watchThread = watchThreads.get(keyToMaintain);
watchThread.setIsRunning(false);
watchThreads.remove(keyToMaintain);
}
}
class GlobalService {
private static Map<String, Foo> foos = new HashMap<>();
private static Map<String, Bar> bars = new HashMap<>();
public static void loadObjects(List<Foo> foos, List<Bar> bars) {
//Parameters that required for watch, so by reflection a thread can access objects
Set<String> paramsToWatchForFoo = new HashSet<>();
paramsToWatchForFoo.add("a");
paramsToWatchForFoo.add("b");
paramsToWatchForFoo.add("c");
for(Foo foo : foos) {
//do some other stuff
WatcherService.registerForWatch(foo, paramsToWatchForFoo);
}
Set<String> paramsToWatchForBar = new HashSet<>();
paramsToWatchForBar.add("aa");
paramsToWatchForBar.add("cc");
for(Bar bar : bars) {
//do some other stuff
WatcherService.registerForWatch(bar, paramsToWatchForBar);
}
}
}
As you can see, I don't want to touch Foo and Bar. And watcher thread in back they do their work without interruption. Is this correct way to implement this? Or any other way to achieve this, required your valuable suggestion.
Have you think to use Aspect approach to achieve this ? I think you can do this in a more simplest way with AOP. Take a look at this : http://www.javaworld.com/article/2073130/performance-monitoring-with-spring-aop.html
Regards,
FT
private void fillInvoiceListForName(String name, ArrayList<Invoice> mInvoices) {
for (SupplierAccount account : listcontracts) {
if (account.getSupplier() != null)
if (account.getSupplier().equals(name)) {
ArrayList<Contract> mContracts = account.getContracts();
for (Contract contract : mContracts) {
mInvoices.addAll(contract.getInvoices());
}
}
}
}
private void fillIncomeListForName(String name, ArrayList<Income> mIncomes) {
for (SupplierAccount account : listcontracts) {
if (account.getSupplier() != null)
if (account.getSupplier().equals(name)) {
ArrayList<Contract> mContracts = account.getContracts();
for (Contract contract : mContracts) {
mIncomes.addAll(contract.getIncomes());
}
}
}
}
private void fillDocumentListForName(String name, ArrayList<Document> mDocuments) {
for (SupplierAccount account : listcontracts) {
if (account.getSupplier() != null)
if (account.getSupplier().equals(name)) {
ArrayList<Contract> mContracts = account.getContracts();
for (Contract contract : mContracts) {
mDocuments.addAll(contract.getDocuments());
}
}
}
}
All of your methods have the iteration in common. What you want to do is abstract the iteration method while allowing the caller to specify an action to perform on the objects being iterated over. Essentially you want to combine an internal iterator (to perform the iteration) with a strategy (to perform the action).
With the Strategy pattern you can define different strategies which all have something in common, and then easily substitute one for the other. In this case, all of your methods collect information from a list of contracts and adds it to a list, though which information they collect varies.
Refactored method
private <E> void fillListForName(String name, List<? super E> listToFill, FillStrategy<E> fillStrategy) {
if (name == null) {
throw new IllegalArgumentException("name cannot be null");
}
for (SupplierAccount account : listContracts) {
if (name.equals(account.getSupplier())) {
List<Contract> contracts = account.getContracts();
for (Contract contract : contracts) {
fillStrategy.execute(listToFill, contract);
}
}
}
}
The FillStrategy interface and an example implementation
interface FillStrategy<T> {
public void execute(List<? super T> listToFill, Contract contract);
}
class InvoiceFillStrategy implements FillStrategy<Invoice> {
#Override
public void execute(List<? super Invoice> listToFill, Contract contract) {
listToFill.addAll(contract.getInvoices());
}
}
Calling the refactored method
List<Invoice> invoices = new ArrayList<Invoice>();
InvoiceFillStrategy invoiceStrategy = new InvoiceFillStrategy();
System.out.println("Invoices for myCorp:");
fillListForName("myCorp", invoices, invoiceStrategy);
for (Invoice i : invoices) {
System.out.println(i);
}
System.out.println("\nInvoices for otherCorp:");
invoices.clear();
fillListForName("otherCorp", invoices, invoiceStrategy);
for (Invoice i : invoices) {
System.out.println(i);
}
Why?
The benefit of this approach is that you can create additional "strategies" without necessarily modifying any of the other classes involved. For example, you could create one that collects all invoices for sums over a given threshold:
class ExpensiveInvoiceFillStrategy implements FillStrategy<Invoice> {
private int minimumAmount;
public ExpensiveInvoiceFillStrategy(int minimumAmount) {
this.minimumAmount = minimumAmount;
}
#Override
public void execute(List<? super Invoice> listToFill, Contract contract) {
for (Invoice invoice : contract.getInvoices()) {
if (invoice.getAmount() >= minimumAmount) {
listToFill.add(invoice);
}
}
}
}
Just implementing this class and then calling fillListForName with an instance of it is enough - no change to fillListForName or Contract is necessary!
There are other ways to implement the iterator method and the strategies - some would even be considered "more pure" or "better" that what I've done here. I chose this approach because it kept the code similar to what you had, and because we're trying to solve a specific problem, not implement general support for internal iterators in Java (smarter guys are already working on that). Just be aware that it's not "perfect" :)
Consider using Guava, it has powerful utilities for manipulating collections. For example, you could use FluentIterable in conjunction with Predicates and Functions, to extract common logic, and use them to transform and filter your collections.
Below I have extracted common elements into the filterAndTransform method which allows you to pass in a Function so you can collect what you like from the Contract object:
private <T> List<T> filterAndTransform(String name, Function<Contract, Iterable<T>> function) {
return FluentIterable.from(listcontracts)
.filter(new HasSupplierPredicate())
.filter(new SupplierNameMatchesPredicate(name))
.transformAndConcat(new Function<SupplierAccount, Iterable<Contract>>() {
#Override public Iterable<Contract> apply(final SupplierAccount account) {
return account.getContracts();
}
})
.transformAndConcat(function)
.toList();
}
private void fillInvoiceListForName(String name, ArrayList<Invoice> mInvoices) {
final Iterable<Invoice> invoices = filter(name,
new Function<Contract, Iterable<Invoice>>() {
#Override public Iterable<Invoice> apply(final Contract contract) {
return contract.getInvoices();
}
});
mInvoices.addAll(invoices);
}
private void fillIncomeListForName(String name, ArrayList<Income> mIncomes) {
final Iterable<Income> incomes = filter(name,
new Function<Contract, Iterable<Income>>() {
#Override public Iterable<Income> apply(final Contract contract) {
return contract.getIncomes();
}
});
mIncomes.addAll(incomes);
}
// etc...
Define an enum, and pass it as a parameter to a method:
public enum ContractValue {
INVOICE, INCOME, DOCUMENT;
}
private void fillIncomeListForName(String name, ArrayList<Income> mIncomes, ContractValue contractValue) {
for (SupplierAccount account : listcontracts) {
if (account.getSupplier() != null)
if (account.getSupplier().equals(name)) {
ArrayList<Contract> mContracts = account.getContracts();
for (Contract contract : mContracts) {
if (contractValue == ContractValue.INCOME) {
mIncomes.addAll(contract.getIncomes());
} else if (contractValue == ContractValue.INVOICE) {
mInvoices.addAll(contract.getInvoices());
} else if (contractValue == ContractValue.DOCUMENT) {
mDocuments.addAll(contract.getDocuments());
}
}
}
}
}
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.