Java Prevent code duplication when getting a list of properties in each object from a list of objects

I have several objects that look like this:

class PhoneNumber
{
   String   getNumber();
   String   getExtension();
   DateTime getLastCalled();
}
class Address
{
   String getCity();
   string getState();
   int    getZip();
}

I would like to be able to take a list of any of these objects and get a list of a specific property. This is a trivial operation if I were to write a function for each property, but as I understand it, it is not good practice to duplicate code so many times.

Therefore, I would like to be able to do something similar for any property in any object:

List<Address> AddressList = getAddresses();
List<String> CityList = getListOfProperties( AddressList, Address.getCity /*<--Instruction as to what property to populate the returned list with */ )

I struggled to do this with generics. I'm not even sure that this is possible, but as I understand it, you can do a lot of magical things with the Java programming language.

+3
5

. , , , , , , ( ..).

, . "get", , getListOfProperties().

public abstract class ListPropertyGetter<R,T>
{
  /** Given a source object, returns some property of type R. */ 
  public abstract R get(T source);

  /** Given a list of objects, use the "get" method to retrieve a single property
      from every list item and return a List of those property values. */
  public final List<R> getListOfProperties(List<T> list)
  {
    List<R> ret = new ArrayList<R>(list.size());
    for(T source : list)
    {
      ret.add(get(source));
    }
    return ret;
  }
}

. , , :

List<PhoneNumber> phoneNumbers = new ArrayList<PhoneNumber>();
// add some PhoneNumbers to the list
List<String> extensions =
  new ListPropertyGetter<String, PhoneNumber>()
  {
    @Override
    public String get(PhoneNumber source)
    {
      return source.getExtension();
    }
  }.getListOfProperties(phoneNumbers);
+2

Introspector, SO.

public <T > List<T > getMemberList( List<? > beanList, 
        String propertyName, Class<T > resultClass ) throws Exception {
    List<T > result = new ArrayList<T >();
    for( Object bean : beanList ) {
        result.add( (T )new PropertyDescriptor( 
                propertyName, bean.getClass() ).getReadMethod().invoke( bean ) );
    }
    return result;
}

:

List<String > result = getMemberList( phonenumberList, "number", String.class );
+2

- , . , . , IDE .

+2

(java.lang.Class java.lang.reflect. *), ; , "get", , "get".

+1

Java; , .

, . , , - , / ; getListOfProperties(AddressList, "city") .

, Apache Commons BeanUtils.

import org.apache.commons.beanutils.BeanUtils;

static List<String> getListOfProperties(List beans, String propertyName) {
    List<String> propertyValues = new ArrayList<String>();
    for (Object bean:beans) {
         propertyValues.add(BeanUtils.getProperty(bean, propertyName));
    }
    return propertyValues;
}
+1

Source: https://habr.com/ru/post/1731272/


All Articles