Home  >  Article  >  How to make a static version of a Map that holds an object's getters/setters?

How to make a static version of a Map that holds an object's getters/setters?

PHPz
PHPzforward
2024-02-06 08:03:03596browse
Question content

I have a map that is built when an object is called, which provides the caller with variable names as keys and getter/setter pairs as values. This works as expected. My problem is that it builds every time I call it, I was wondering if there is a way to declare it as static and just provide the object that I want to call it on so that I don't build the map every time because Getters and setters do not change at runtime.

I have:

package main;
import org.javatuples.Pair;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Supplier;

public interface MapPackHelperI 
{
     public Map<String, Pair<Supplier, Consumer>> getNameToGetterSetterMap();    
}
package main;

import java.util.List;
import java.util.Map;
import java.util.HashMap;
import org.javatuples.Pair;
import java.util.function.Consumer;
import java.util.function.Supplier;

public class SomeStruct implements MapPackHelperI
{
    private long somelong;
    private String somestring;
    private List<Float> somelistfloat;
    private SomeEnum someenum;

    public  Map<String, Pair<Supplier, Consumer>> getNameToGetterSetterMap()
    {
        Map<String, Pair<Supplier, Consumer>> nameToGetterSetterMap = new HashMap<>();        
        nameToGetterSetterMap.put("somelong", Pair.with( this::getSomelong, (Consumer<Long>)this::setSomelong));
        nameToGetterSetterMap.put("somestring", Pair.with( this::getSomestring, (Consumer<String>)this::setSomestring));
        nameToGetterSetterMap.put("somelistfloat", Pair.with( this::getSomelistfloat, (Consumer<List<Float>>)this::setSomelistfloat));
        nameToGetterSetterMap.put("someenum", Pair.with( this::getSomeenum, (Consumer<SomeEnum>)this::setSomeenum));
        return nameToGetterSetterMap;
    }

    public long getSomelong() {
        return this.somelong;
    }

    public void setSomelong(long somelong) {
        this.somelong = somelong;
    }

    public String getSomestring() {
        return this.somestring;
    }

    public void setSomestring(String somestring) {
        this.somestring = somestring;
    }

    public List<Float> getSomelistfloat() {
        return this.somelistfloat;
    }

    public void setSomelistfloat(List<Float> somelistfloat) {
        this.somelistfloat = somelistfloat;
    }

    public SomeEnum getSomeenum() {
        return this.someenum;
    }

    public void setSomeenum(SomeEnum someenum) {
        this.someenum = someenum;
    }

   // ... hashcode, toString, and equals, not relevant for the example
}

This allows me to do from elsewhere:

public static String serialize(MapPackHelperI objectToSerialize) 
{
   Map<String, Pair<Supplier, Consumer>> nameToGetterSetterMap = objectToSerialize.getNameToGetterSetterMap();
   for(Entry<String, Pair<Supplier, Consumer>> current : nameToGetterSetterMap.entrySet())
   {
       String name = current.getKey();
       Supplier getter = current.getValue().getValue0();
       //code that serializes into string with name and getter regardless of the MapPackHelperI I pass in
   }

  // return the string representation of the object. I have another method that uses the same map to go the other way with the setter.
}

Like I said, this works, but every time I call it I instantiate and populate the map.

Is there a way for SomeStruct to have a public static Map7ac420dc38be31c2cf1f91a147206a67> nameToGetterSetterMap = new HashMapa8093152e673feb7aba1828c43532094(); (or some etc. (effective), so public Map05ec053c74fe00d54b1c26da660af901> getNameToGetterSetterMap() takes the instantiated parameter as argument SomeStruct and applies the call only to that specific object.

I tried making a static map and filling it with SomeStruct::getSomelong etc. but the compiler said I can't do that.


Correct answer


Member fields

The answer seems so obvious, I must be missing something: cache newly constructed mappings as private member fields.

public class SomeStruct implements MapPackHelperI
{
    private long somelong;
    private String somestring;
    private List<Float> somelistfloat;
    private SomeEnum someenum;
    private Map<String, Pair<Supplier, Consumer>> map = 
        Map.of( 
            "somelong", Pair.with( this::getSomelong, (Consumer<Long>)this::setSomelong) ,
            "somestring", Pair.with( this::getSomestring, (Consumer<String>)this::setSomestring) ,
            "somelistfloat", Pair.with( this::getSomelistfloat, (Consumer<List<Float>>)this::setSomelistfloat) ,
            "someenum", Pair.with( this::getSomeenum, (Consumer<SomeEnum>)this::setSomeenum)
        ) ;

    public  Map<String, Pair<Supplier, Consumer>> getNameToGetterSetterMap()
    {
        return this.map ;
    }

…

Please note that Map.of is cannot be modified.

You should be able to set the map member variable to static, but unless you are sure you are instantiating SomeStruct countless times, I think this Micro-optimizations are not worth the trouble.

The above is the detailed content of How to make a static version of a Map that holds an object's getters/setters?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete