Java 使用泛型创建分层对象的分层存储

Java 使用泛型创建分层对象的分层存储,java,generics,collections,Java,Generics,Collections,我正在开发一个解析/验证基础设施来处理对象 在我的申请中。解析过程非常快,而且 验证过程非常缓慢,通常不会失败。解析 流程生成对象Foo和验证流程 另外生成ExtendedFoo 公共类Foo{ 私人长id; } 公共类ExtendedFoo扩展Foo{ 私有布尔值是有效的; } 解析过程的输出存储在这样的类中(除了Foo),还有其他类型的对象: 公共类存储{ 私有映射foos=newhashmap(); 私有映射栏=新的HashMap(); 公共映射getFoos(){return foos

我正在开发一个解析/验证基础设施来处理对象 在我的申请中。解析过程非常快,而且 验证过程非常缓慢,通常不会失败。解析 流程生成对象
Foo
和验证流程 另外生成
ExtendedFoo

公共类Foo{
私人长id;
}
公共类ExtendedFoo扩展Foo{
私有布尔值是有效的;
}
解析过程的输出存储在这样的类中(除了
Foo
),还有其他类型的对象:

公共类存储{
私有映射foos=newhashmap();
私有映射栏=新的HashMap();
公共映射getFoos(){return foos;}
公共映射getBars(){return bars;}
}
而该存储是该应用程序所需的最低基本信息 应用程序

当我想运行附加验证时,我想使用 以下结构:

公共类扩展存储扩展存储{
公共地图getFoos(){
return(Map)super.getFoos();
}
//由于没有验证,所以未扩展条
}
但是“未经检查的演员阵容”让我觉得有更好的方法 解决这个问题


解决这个问题的java通用“惯用”方法是什么?

通用分层存储方法的一些想法包括:

  • 定义一个子类来处理决定结构“是否有效”可能是自限制的。另一种选择是将逻辑放在存储级别,而不是特定于结构
  • 在存储类型中提供助手方法,而不是返回底层映射,这可能会提高可用性
  • 下面包括泛型类型存储的示例方法。数据保存在两个映射中,一个保存已验证的数据,另一个存储已解析的数据。创建时,将提供parsedData映射和验证函数。当用户请求已验证的数据时,如果尚未计算该数据,则会将其删除

        public static class TypeStore<T>
        {
            private final Map<String, T> validData;
            private final Map<String, T> parsedData;
            private final Predicate<? super T> isValid;
            public TypeStore(Map<String, T> parsedData, Predicate<? super T> isValid)
            {
                this.validData = new HashMap<>();
                this.parsedData = parsedData;
                this.isValid = isValid;
            }
    
            public Optional<T> getValue(String key) { return Optional.ofNullable(parsedData.get(key)); }
            public Optional<T> getValidValue(String key) { return Optional.ofNullable(validData.computeIfAbsent(key, k -> getValue(k).filter(isValid).orElse(null))); }
        }
    
    公共静态类类型存储
    {
    私人最终地图validData;
    私人最终地图数据;
    私有终结谓词
    “此存储是应用程序所需的最低基本信息…”

    这表明需要一个统一的抽象概念,如

    public interface Storable< MBI > { 
        
        MBI getMinimumBasicInformation( );
    }
    
    以及类型安全实现(
    未检查的警告

    公共类扩展存储,MBI>扩展存储{
    公共扩展存储区(){super();}
    公共扩展存储(Map存储){super(存储);}
    @凌驾
    公共映射getStored(){
    返回super.getStored();
    }
    }
    
    然后是一个示例,它存储了一个对象()

    公共类Foo实现可存储{
    保护长id;
    @凌驾
    public Long getMinimumBasicInformation(){返回this.id;}
    }
    
    我很可能会使用流来处理这些IRL。但由于这只是一个简单的实验,仅仅意味着四处走动

    …
    StorefooStore=newextendedstore<>(新HashMap<>(of(“Foo”,newextendedfoo(1L,true),“Foo”,newextendedfoo(2L,true),“Foo”,newextendedfoo(3L,true));
    Mapfoos=fooStore.getStored();
    fooStore.store(“fuBar”,新扩展的foo(4L,true));
    StorebarStore=newextendedstore<>();
    MapBar=barStore.getStored();
    store(“bar”,新扩展的bar(“bar”,true));
    …
    
    不是答案,但是…如果使用
    Map
    你会非常痛苦,因为你不能使用此类型向映射添加任何内容。只需使用
    Map
    或引入一个类型参数。如果不了解你的代码库,我可能会编写一个抽象方法
    validate()
    用于返回具体的
    ExtendedFoo
    实例的
    Foo
    (此时,我不再扩展
    Foo
    ,而是使
    ExtendedFoo
    更像一个带有完全封装字段的响应类型对象),它可以返回一个急切缓存的值,也可以动态地延迟验证。我可能根本不会使用映射,如果可能包含的值提前知道,并且您没有使用直接用户输入字符串,我会使用一些自定义对象和字段(糟糕!)当您说:“
    //bar没有扩展,因为没有验证”
    ”,这是否意味着
    ExtendedStore
    将只与
    ExtendedFoos
    一起工作?“…(除了
    Foo
    之外还有其他类型的对象)…“-这是否意味着每次在应用程序中引入新类型的对象时,您都计划为这些新类型中的每一个实现另一个
    Store.getXXX()
    ?缺少一些相关的东西。例如,当您有一个声明,如
    private-Map-foos=new-HashMap();
    ,如何填充此映射?“…可以将多个类型存储添加到配置类…”-这是否意味着每次将新类型的对象引入应用程序时,您都计划实现另一个
    类型存储(新HashMap()…
    对于这些新类型中的每一个?通常使用AppConfig示例是因为原始问题在“Store”类中使用了多个映射。TypeStore寻求提供对底层类型(例如:已验证和未验证视图)的差异访问,其中一个视图的计算成本可能很高(已验证视图).一般来说,可以在需要的地方创建和使用TypeStore,但有时在公共位置拥有配置数据会更好。
    public interface Storable< MBI > { 
        
        MBI getMinimumBasicInformation( );
    }
    
    public class Store< F extends Storable< MBI >, MBI > {
    
        protected Map< String, F > stored;
        …
        public Map< String,  F > getStored( ) { return stored; }
        
        public void store( String key, F storable ){  this.stored.put( key, storable); }
    
    }
    
    public class ExtendedStore< F extends Storable< MBI >, MBI > extends Store< F, MBI > {
    
        public ExtendedStore( ) { super( ) ; }
        
        public ExtendedStore( Map< String, F > stored ) { super( stored ); }
        
        @Override
        public Map< String, F > getStored( ) {
            return super.getStored( );
        }
    }
    
    public class Foo implements Storable< Long > {
        
        protected Long id;
        
        @Override
        public Long getMinimumBasicInformation( ) { return this.id; }
    }
    
    …
    Store< Foo, Long > fooStore = new ExtendedStore< >( new HashMap< > ( of( "foo", new ExtendedFoo( 1L, true ) , "FOO", new ExtendedFoo( 2L, true ), "Foo", new ExtendedFoo( 3L, true ) ) ) );
            
    Map< String, Foo > foos = fooStore.getStored( );
            
    fooStore.store( "fuBar", new ExtendedFoo( 4L, true ) );
            
    Store< Bar, String > barStore = new ExtendedStore< >( );
            
    Map< String, Bar > bars = barStore.getStored( );
            
    barStore.store( "bar", new ExtendedBar( "bar", true ) );
    …