Java: Convert a collection of classA to collection of classB
Given开发者_如何学JAVA a List of Foo myFoos, I need to map those to a collection of a different class, say Bar. I do it like this now:
List<Bar> myBars = new...
for(Foo f : foos) {
Bar b = new Bar();
b.setAProperty(f.getProperty);
b.setAnotherProp(f.getAnotherProp);
myBars.add(b);
}
So, is there an easier way to do this? Granted this is pretty easy, but I'm wondering if there's any magic out there that would morph the foos to bars without having to manually walk the list, particularly because my input list can be big.
If not, do you guys know if the compiler does anything to optimize this? I'm worried mainly about performance.Thanks!
--
LlappallYou can't really avoid walking the list, because you have to convert every item!
But you can simplify your syntax if you write a Bar
constructor that takes a Foo
. Then your loop can become:
for(foo f : foos) {
myBars.add(new Bar(f));
}
Depending on your scenario, an alternative is to not create the list of Bar
s at all. Instead, you can simply add a Foo.getAsBar()
method, so that you dynamically generate a Bar
object as required. If the number of elements in the container is higher than the total number of times that you'll need to access them, then this may be more efficient.
public Bar(Foo f){
this.a = f.a;
this.b = f.b;
}
for (Foo f : myFoos){
myBars.add(new Bar(f));
}
One idea which is not a general solution, but could be appropriate in some situations:
Pull the properties
Instead of pushing the properties from Foo to Bar whenever a Bar is instantiated, just associate a Foo to a new Bar and map the properties in the property getters.
- This is good, if not all instances / properties of Bar will be accessed by clients anyway.
- But there is a preformance penalty, if Bar instances / properties are accessed repeatedly by clients.
public class Bar { Foo foo; public Bar(Foo foo) { this.foo = foo; } public int getPropertyA() { return foo.getPropertyA(); } public int getAnotherProperty() { return foo.getAnotherProperty(); } }
This does not prevent you from looping over Foos to instantiate Bars. But it delays the effort to map properties.
Another idea, which is - granted - approriate in very rare cases only.
Implement (kind of) a Fyweight pattern
Prerequisite: The set of properties of Foo
and Bar
is the same.
- Put the common properties of
Foo
andBar
into an external class, sayProperties
. - Implement a property of type
Properties
for Foo and Bar. - When you create a new instance of
Bar
and want to initialize it fromFoo
, just pass the Properties from theFoo
instance to the newBar
instance.
Pros:
- No need to create copies of properties
Cons:
- Property set must be the same for Foo and Bar
- Extra indirection (=overhead) at property access
- Changes to the properties of Bar affect the originating properties of Foo.
public class Properties {
public int getPropertyA() {..}
public int getAnotherProperty() {..}
}
public class Foo {
Properties properties;
public Foo(Properties properties)
this.properties = properties;
}
public Properties getProperties() {
return properties;
}
}
public class Bar {
Properties properties;
public Foo(Properties properties)
this.properties = properties;
}
public Properties getProperties() {
return properties;
}
}
//Client code:
//Access properties:
int i = foo.getProperties().getPropertyA();
//Map Foos to Bars
for (Foo foo: foos) {
Bar bar = new Bar(foo.getProperties());
//Do something with bar
}
精彩评论