Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #27727 > unrolled thread

Parameterized collection catch-22

Started byzapanaz_googlegroups@hotmail.com
First post2014-03-11 09:36 -0700
Last post2014-03-16 17:06 -0700
Articles 7 — 4 participants

Back to article view | Back to comp.lang.java.programmer


Contents

  Parameterized collection catch-22 zapanaz_googlegroups@hotmail.com - 2014-03-11 09:36 -0700
    Re: Parameterized collection catch-22 markspace <markspace@nospam.nospam> - 2014-03-11 11:14 -0700
      Re: Parameterized collection catch-22 zapanaz_googlegroups@hotmail.com - 2014-03-16 17:04 -0700
        Re: Parameterized collection catch-22 Lew <lewbloch@gmail.com> - 2014-03-22 15:42 -0700
          Re: Parameterized collection catch-22 zapanaz_googlegroups@hotmail.com - 2014-03-23 16:35 -0700
    Re: Parameterized collection catch-22 Daniel Pitts <newsgroup.nospam@virtualinfinity.net> - 2014-03-12 09:51 -0700
      Re: Parameterized collection catch-22 zapanaz_googlegroups@hotmail.com - 2014-03-16 17:06 -0700

#27727 — Parameterized collection catch-22

Fromzapanaz_googlegroups@hotmail.com
Date2014-03-11 09:36 -0700
SubjectParameterized collection catch-22
Message-ID<6f84734b-69d5-471c-b041-8d37dd5657e5@googlegroups.com>
I have a parent class, AddressInfo. An abstract class. Two classes inherit from AddressInfo, ShippingInfo and BillingInfo. ShippingInfo and BillingInfo are nearly identical, and are identical for what I'm doing here. 

The example code I'm posting is stripped down, in case you wonder why it's a little dumb. 

I have two methods, 

public void mergeBillingInfoLists(List<BillingInfo> list1, List<BillingInfo> list2) { 
list1.add(1, list2.get(0)); 
} 

And one for ShippingInfo which is identical, just with ShippingInfo where BillingInfo is. 

I want to combine the two methods, which are very redundant. It seems like it should be possible, given that they have a common parent class. I can do this: 

public void mergeAddressInfo(List<? extends AddressInfo> list1, List<? extends AddressInfo> list2) { 
list1.add(1, list2.get(0)); 
} 

But Java won't allow this, it won't allow the add(). All it knows about what list2 contains is that it's something that descends from AddressInfo, so even if I pass in 2 List<BillingInfo>'s, inside the code it doesn't know they're the same classes. 

Does anybody offhand know a way to do this? (Without throwing away the parameterization :) ) 

I don't necessarily need to use this exact approach, just anything that would allow me to combine the two methods into one method. In fact I have quite a lot of this kind of redundancy in the code base I'm working with, so this is something I'm running into a lot.

Thanks for any help

-- 
Joe Cosby
http://joecosby.com/ 
`She knew how to embroider and milk a cow.' -- Connie Willis, Doomsday Book

:: Currently listening to Oxygene, Pt. II, 1976, by Jean Michel Jarre, from "Oxygene"

[toc] | [next] | [standalone]


#27729

Frommarkspace <markspace@nospam.nospam>
Date2014-03-11 11:14 -0700
Message-ID<lfnjq6$t9m$1@dont-email.me>
In reply to#27727
On 3/11/2014 9:36 AM, zapanaz_googlegroups@hotmail.com wrote:
 > public void mergeAddressInfo(List<? extends AddressInfo> list1,
                 List<? extends AddressInfo> list2)

   {
 >       list1.add(1, list2.get(0));
 > }
 >
> But Java won't allow this, it won't allow the add(). All it knows
> about what list2 contains is that it's something that descends from
> AddressInfo, so even if I pass in 2 List<BillingInfo>'s, inside the
> code it doesn't know they're the same classes.

Yes.  Consider that your two subtypes, BillingInfo and ShippingInfo, 
both match the wildcard <? extends AddressInfo>.  So it's perfectly 
legal to pass one of each to the mergeAddressInfo() method.

List<BillingInfo> b = ...;
List<ShippingInfo> s = ...;

x.mergeAddressInfo( b, s ); // works

So Java is telling you you can't call list1.add() because it assumes you 
don't want to mix up a list of two different types.

So you have to tell the compiler that both parameters are of the same 
type.  One way to do that is to use a generic method:

public <A extends AddressInfo> void  mergeAddressInfo( List<A> a,
                 List<A> b )
{...

Now the compiler knows that a and b are of the same type.  It will 
enforce that when you call the method (give you an error) and it will 
allow operations that make sense for lists of the same type.

(Not compiled or tested.)

C.f. the Java tutorial.

<http://docs.oracle.com/javase/tutorial/java/generics/capture.html>
<http://docs.oracle.com/javase/tutorial/java/generics/methods.html>

[toc] | [prev] | [next] | [standalone]


#27768

Fromzapanaz_googlegroups@hotmail.com
Date2014-03-16 17:04 -0700
Message-ID<2fce5555-a057-4046-8fb1-de43d7175ece@googlegroups.com>
In reply to#27729
On Tuesday, March 11, 2014 11:14:27 AM UTC-7, markspace wrote:
> 
> public <A extends AddressInfo> void  mergeAddressInfo( List<A> a,
> 
>                  List<A> b )
> 
> {...
> 
> 
> 
> Now the compiler knows that a and b are of the same type.  It will 
> 
> enforce that when you call the method (give you an error) and it will 
> 
> allow operations that make sense for lists of the same type.
> 

Ah thanks very much. I should have known that.

They added generics to Java after I learned it, I still don't think of them.

> 
> 
> (Not compiled or tested.)
> 

it's OK, I see what you're saying


-- 
Joe Cosby

Agent 99: Max, that knife missed you by inches. 
Maxwell Smart: You think it's some kind of warning?

:: Currently listening to All My Life, 1972, by Uriah Heep, from "Demons and Wizards"

[toc] | [prev] | [next] | [standalone]


#27814

FromLew <lewbloch@gmail.com>
Date2014-03-22 15:42 -0700
Message-ID<1f8a0985-e157-4f91-b30e-0ff7da42c8c7@googlegroups.com>
In reply to#27768
zapanaz_go...@hotmail.com wrote:
> Ah thanks very much. I should have known that.
> 
> They added generics to Java after I learned it, I still don't think of them.

That was ten years ago. Two versions of Java have already gone obsolete since generics came in, and the fourth version to use them just came out.

You might want to consider that it's been long enough. 

-- 
Lew
 

[toc] | [prev] | [next] | [standalone]


#27830

Fromzapanaz_googlegroups@hotmail.com
Date2014-03-23 16:35 -0700
Message-ID<cbc4a95e-2a76-4a92-9e6b-17321b8b01b1@googlegroups.com>
In reply to#27814
On Saturday, March 22, 2014 3:42:58 PM UTC-7, Lew wrote:
> zapanaz_go...@hotmail.com wrote:
> 
> > Ah thanks very much. I should have known that.
> 
> > 
> 
> > They added generics to Java after I learned it, I still don't think of them.
> 
> 
> 
> That was ten years ago. Two versions of Java have already gone obsolete since generics came in, and the fourth version to use them just came out.
> 
> 
> 
> You might want to consider that it's been long enough. 
> 
> 
> 

OK Dad



[toc] | [prev] | [next] | [standalone]


#27742

FromDaniel Pitts <newsgroup.nospam@virtualinfinity.net>
Date2014-03-12 09:51 -0700
Message-ID<lg0Uu.13736$Nm1.6311@fx22.iad>
In reply to#27727
On 3/11/14 9:36 AM, zapanaz_googlegroups@hotmail.com wrote:
> I have a parent class, AddressInfo. An abstract class. Two classes inherit from AddressInfo, ShippingInfo and BillingInfo. ShippingInfo and BillingInfo are nearly identical, and are identical for what I'm doing here.
>
> The example code I'm posting is stripped down, in case you wonder why it's a little dumb.
>
> I have two methods,
>
> public void mergeBillingInfoLists(List<BillingInfo> list1, List<BillingInfo> list2) {
> list1.add(1, list2.get(0));
> }
>
> And one for ShippingInfo which is identical, just with ShippingInfo where BillingInfo is.
>
> I want to combine the two methods, which are very redundant. It seems like it should be possible, given that they have a common parent class. I can do this:
>
> public void mergeAddressInfo(List<? extends AddressInfo> list1, List<? extends AddressInfo> list2) {
> list1.add(1, list2.get(0));
> }
>
> But Java won't allow this, it won't allow the add(). All it knows about what list2 contains is that it's something that descends from AddressInfo, so even if I pass in 2 List<BillingInfo>'s, inside the code it doesn't know they're the same classes.
>
> Does anybody offhand know a way to do this? (Without throwing away the parameterization :) )
>
> I don't necessarily need to use this exact approach, just anything that would allow me to combine the two methods into one method. In fact I have quite a lot of this kind of redundancy in the code base I'm working with, so this is something I'm running into a lot.
>
> Thanks for any help
>

There are three ways write that so it works as you desire:

Method one:
public <T> void mergeInfo(List<? super T> list1,List<? extends T> list2)

T is any type at all.
list1 can be any type of List of <T> or List of <SuperclassOfT>  This 
means the list1 can accept any object that is assignable *from* <T>.  It 
is unknown the type that it produces.

list2 can be any type of List of <T> or List of <SubclassOfT>.  It will 
produce objects that assignable *to* <T>.



Method two:
public <T> void mergeInfo(List<T> list1,List<? extends T> list2)

T is any type at all.
list1 can be any type of List of <T>, but not any other type parameter. 
  list1 can therefor produce and accept any object assignable to or from <T>

list2 is the same as list2 from Method One


Method three:
public <T> void mergeInfo(List<T> list1,List<T> list2)

T is any type at all.
list1 can be any type of List of <T>, but not any other type parameter. 
  list1 can therefor produce and accept any object assignable to or from <T>

list2 must be a List with the exact same type parameter as list1.


And finally, one last note.  For any of the examples above, if you want 
to ensure that you're only dealing with subclasses of AddressInfo:

public <T extends AddressInfo> void mergeInfo(... yata yata)


This says "T must be AddressInfo or a subclass thereof".

In your particular case, I would combine this with Method Three. Though 
often with generic functions, you're better off with Method one.

The rule-of-thumb I use is: In your scope if you have an object that 
only accepts <T> use <? super T>. If you have an object that only 
produces <T>, use <? extends T>.  If you have an object that produces 
and accepts <T>, then use <T>.  I'm talking about "produces" or 
"accepts" in what you call, not what methods are available.

HTH.

[toc] | [prev] | [next] | [standalone]


#27769

Fromzapanaz_googlegroups@hotmail.com
Date2014-03-16 17:06 -0700
Message-ID<8bcf3da9-175d-4894-b80f-657d9f39afae@googlegroups.com>
In reply to#27742
On Wednesday, March 12, 2014 9:51:33 AM UTC-7, Daniel Pitts wrote:
> On 3/11/14 9:36 AM, zapanaz_...@hotmail.com wrote:
> 
> > I have a parent class, AddressInfo. An abstract class. Two classes inherit from AddressInfo, ShippingInfo and BillingInfo. ShippingInfo and BillingInfo are nearly identical, and are identical for what I'm doing here.
> 
> >
> 
> > The example code I'm posting is stripped down, in case you wonder why it's a little dumb.
> 
> >
> 
> > I have two methods,
> 
> >
> 
> > public void mergeBillingInfoLists(List<BillingInfo> list1, List<BillingInfo> list2) {
> 
> > list1.add(1, list2.get(0));
> 
> > }
> 
> >
> 
> > And one for ShippingInfo which is identical, just with ShippingInfo where BillingInfo is.
> 
> >
> 
> > I want to combine the two methods, which are very redundant. It seems like it should be possible, given that they have a common parent class. I can do this:
> 
> >
> 
> > public void mergeAddressInfo(List<? extends AddressInfo> list1, List<? extends AddressInfo> list2) {
> 
> > list1.add(1, list2.get(0));
> 
> > }
> 
> >
> 
> > But Java won't allow this, it won't allow the add(). All it knows about what list2 contains is that it's something that descends from AddressInfo, so even if I pass in 2 List<BillingInfo>'s, inside the code it doesn't know they're the same classes.
> 
> >
> 
> > Does anybody offhand know a way to do this? (Without throwing away the parameterization :) )
> 
> >
> 
> > I don't necessarily need to use this exact approach, just anything that would allow me to combine the two methods into one method. In fact I have quite a lot of this kind of redundancy in the code base I'm working with, so this is something I'm running into a lot.
> 
> >
> 
> > Thanks for any help
> 
> >
> 
> 
> 
> There are three ways write that so it works as you desire:
> 
> 
> 
> Method one:
> 
> public <T> void mergeInfo(List<? super T> list1,List<? extends T> list2)
> 
> 
> 
> T is any type at all.
> 
> list1 can be any type of List of <T> or List of <SuperclassOfT>  This 
> 
> means the list1 can accept any object that is assignable *from* <T>.  It 
> 
> is unknown the type that it produces.
> 
> 
> 
> list2 can be any type of List of <T> or List of <SubclassOfT>.  It will 
> 
> produce objects that assignable *to* <T>.
> 
> 
> 
> 
> 
> 
> 
> Method two:
> 
> public <T> void mergeInfo(List<T> list1,List<? extends T> list2)
> 
> 
> 
> T is any type at all.
> 
> list1 can be any type of List of <T>, but not any other type parameter. 
> 
>   list1 can therefor produce and accept any object assignable to or from <T>
> 
> 
> 
> list2 is the same as list2 from Method One
> 
> 
> 
> 
> 
> Method three:
> 
> public <T> void mergeInfo(List<T> list1,List<T> list2)
> 
> 
> 
> T is any type at all.
> 
> list1 can be any type of List of <T>, but not any other type parameter. 
> 
>   list1 can therefor produce and accept any object assignable to or from <T>
> 
> 
> 
> list2 must be a List with the exact same type parameter as list1.
> 
> 
> 
> 
> 
> And finally, one last note.  For any of the examples above, if you want 
> 
> to ensure that you're only dealing with subclasses of AddressInfo:
> 
> 
> 
> public <T extends AddressInfo> void mergeInfo(... yata yata)
> 
> 
> 
> 
> 
> This says "T must be AddressInfo or a subclass thereof".
> 
> 
> 
> In your particular case, I would combine this with Method Three. Though 
> 
> often with generic functions, you're better off with Method one.
> 
> 
> 
> The rule-of-thumb I use is: In your scope if you have an object that 
> 
> only accepts <T> use <? super T>. If you have an object that only 
> 
> produces <T>, use <? extends T>.  If you have an object that produces 
> 
> and accepts <T>, then use <T>.  I'm talking about "produces" or 
> 
> "accepts" in what you call, not what methods are available.
> 
> 
> 
> HTH.


Thanks very much

-- 
Joe Cosby

Agent 99: Max, that knife missed you by inches.
Maxwell Smart: You think it's some kind of warning?

:: Currently listening to All My Life, 1972, by Uriah Heep, from "Demons and Wizards" 

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.java.programmer


csiph-web