Aritz
Aritz

Reputation: 31649

Spring create a TreeMap with custom Comparator and populate it

In Java language, it's possible to create TreeMaps using our own Comparator class. Now, I want to create one of that maps and assign it to one of my beans. I also know map values beforehand and I'm interested in leaving Spring inject them. The question is, can a map type be declared, built with a constructor param (I need it to pass the Comparator class) and be value-injected using Spring?

This kind of declaration works, but no value can be injected later:

<bean id="antennaFilteringManagerMap" class="java.util.TreeMap">
    <constructor-arg ref="nameComparator" />
</bean>

<bean id="nameComparator" class="com.tadic.model.detector.Antenna.NameComparator" />

On the other hand, if I use Spring map utilities, there are some ways to specify map's class, but the constructor arg cannot be passed:

<bean class="org.springframework.beans.factory.config.MapFactoryBean">
    <property name="targetMapClass">
        <value>java.util.TreeMap</value>
    </property>
    <property name="sourceMap">
        <map>
            <entry key-ref="antenna1" value-ref="locationEventFilteringManager1" />
        </map>
    </property>
</bean>

OR

<util:map map-class="java.util.TreeMap">
    <entry key-ref="antenna1" value-ref="locationEventFilteringManager1" />
</util:map>

Upvotes: 3

Views: 1689

Answers (1)

Aritz
Aritz

Reputation: 31649

That's a nice workaround. I defined a subclass which extends from TreeMap for my specific case. This class adds the Comparator I want to use by default in the constructor:

public static class LocationEventFilteringManagerMap extends
        TreeMap<Antenna, LocationEventFilteringManager> {

    public LocationEventFilteringManagerMap() {
        super(new Antenna.NameComparator());
    }

}

After that, I only need to specify the map-class to the util-map tag:

<property name="_LocationEventFilteringManagerMap">
    <util:map
        map-class="mypackage.MyBean.LocationEventFilteringManagerMap">
        <entry key-ref="antenna1" value-ref="locationEventFilteringManager1" />
    </util:map>
</property>

Forcing the new class to construct the Map in that way, I avoid the needing of the constructor-arg injection for the Map and I can easily populate it.

Upvotes: 1

Related Questions