Home > database >  How to get element from a list of interface implementations by implementation name
How to get element from a list of interface implementations by implementation name

Time:04-06

I have a list of implementations to SomeInterface

List<SomeInterface> listOfThingsThatImplementsSomeInterface

I want to extract a specific implementation from the list according to its class name

private SomeInterface getThisType(SomeInterfaceImpl myType) {
    SomeInterfaceImpl impl = null
    for (SomeInterface current: listOfThingsThatImplementsSomeInterface) {
        if (current instanceof myType) {
            impl = current
            break;
        }
    }
    return impl;
}

Is that possible in Java? should I be using generics?

CodePudding user response:

First you need the Class instance of the desired class (which you have, you mention "according to its class name"). You can get a Class instance from the class name using

Class<?> cls = SomeInterfaceImpl.class;

or if you have the class name as a String:

Class<?> cls = Class.forName("package.ClassName")

or from an instance using

SomeInterfaceImpl myType = ...;
Class<?> cls = myType.getClass()

Then you can call this method, assuming your have a List<SomeInterface> listOfThingsThatImplementsSomeInterface somewhere:

private SomeInterface getThisType(Class<?> myType) {
    for (SomeInterface current: listOfThingsThatImplementsSomeInterface) {
        if (myType.isInstance(current)) {
            return current;
        }
    }
    return null; //nothing found
}

CodePudding user response:

The method should take the class as parameter. Let's say your interface is T, you can receive a parameter of type Class<? extends T>

Then go through the list and check for an element with the same class

Here is an example that should work:

private static <T> Optional<T> getThisType(
        List<T> listOfThingsThatImplementsInterfaceT, 
        Class<? extends T> klass) {
    return listOfThingsThatImplementsInterfaceT.stream()
            .filter(klass::isInstance)
            .findFirst();
}

Test with a list of Serializable

List<Serializable> listOfThingsThatImplementsSerializable = Arrays.asList(
    new Integer(1), new Float(2), new Double(3)
);

System.out.println(
    getThisType(listOfThingsThatImplementsSerializable, Float.class)
);

Looking for the Float returns Optional[2.0]

CodePudding user response:

Suppose we have the desired implementation Class instance, (refer to @f1sh answer if the class is Class<?>), it can be done using Stream,

private <T extends SomeInterface> Optional<T> getThisType(Class<T> type) {
    return this.someInterfaceList.stream().filter(type::isInstance)
            .map(type::cast).findFirst();
}

The key to match the type is using Class#isInstance.
Some points to note:

  1. Make method return type generic so no cast is needed.
  2. Class#cast can be used to convert the return type of the Stream.
  3. Use Optional to handle case when no element matched.

Full example

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class FilterByClass {

    List<SomeInterface> someInterfaceList = new ArrayList<>();

    public static void main(String[] args) {
        FilterByClass filterByClass = new FilterByClass();
        filterByClass.someInterfaceList = List.of(new SomeInterfaceImplA(), new SomeInterfaceImplB(), new SomeInterfaceImplC());
        System.out.println(filterByClass.getThisType(SomeInterfaceImplA.class).get().name());
        System.out.println(filterByClass.getThisType(SomeInterfaceImplB.class).get().name());
        System.out.println(filterByClass.getThisType(SomeInterfaceImplC.class).get().name());
    }

    private <T extends SomeInterface> Optional<T> getThisType(Class<T> type) {
        return this.someInterfaceList.stream().filter(type::isInstance)
                .map(type::cast).findFirst();
    }

    public interface SomeInterface {
        default String name() {
            return this.getClass().getSimpleName();
        }
    }

    public static class SomeInterfaceImplA implements SomeInterface { }

    public static class SomeInterfaceImplB implements SomeInterface { }

    public static class SomeInterfaceImplC implements SomeInterface { }
}
  • Related