首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用泛型创建分层对象的分层存储

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

Stack Overflow用户
提问于 2020-09-18 02:55:57
回答 2查看 53关注 0票数 0

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

代码语言:javascript
复制
public class Foo {
    private Long id;
}

public class ExtendedFoo extends Foo {
    private Boolean isValid;
}

解析过程的输出存储在这样的类中(除了Foo之外还有其他类型的对象):

代码语言:javascript
复制
public class Store {

    private Map<String, ? extends Foo> foos = new HashMap<String, Foo>();
    private Map<String, ? extends Bar> bars = new HashMap<String, Bar>();

    public Map<String, ? extends Foo> getFoos() { return foos; }
    public Map<String, ? extends Bar> getBars() { return bars; }

}

这个存储是应用程序所需的最低基本信息。

当我想要运行额外的验证时,我想使用以下结构:

代码语言:javascript
复制
public class ExtendedStore extends Store {

    public Map<String, ? extends ExtendedFoo> getFoos() {
        return (Map<String, ? extends ExtendedFoo>) super.getFoos();
    }
    // bar is not extended since there is no validation
}

但“未经检查的强制转换”让我认为有更好的方法来解决这个问题。

对于这个问题,java通用的“惯用”方法是什么?

EN

回答 2

Stack Overflow用户

发布于 2020-09-18 03:46:19

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

  1. 定义一个子类来处理结构'isValid‘是否可能是自我限制的决定。一种选择是将逻辑放在商店级别,而不是特定于返回底层地图的struct.
  2. Instead,在商店类型中提供帮助器方法可能会提高可用性。

下面包括一个泛型类型存储的示例方法。数据在两个映射中维护,一个保存验证的数据,另一个存储解析的数据。在创建时,将提供parsedData映射和验证函数。当用户请求验证数据时,如果它还没有被计算,它将被计算。

代码语言:javascript
复制
    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))); }
    }

然后可以将多个TypeStores添加到一个配置类

代码语言:javascript
复制
    public static class ApplicationConfig
    {
        public final TypeStore<Object>  type1 = new TypeStore<>(new HashMap<>(), elem -> { /*Expensive Operation*/ return true; });
        public final TypeStore<Integer> type2 = new TypeStore<>(new HashMap<>(), elem -> { /*Expensive Operation*/ return true; });
        public final TypeStore<String> type3  = new TypeStore<>(new HashMap<>(), elem -> { /*Expensive Operation*/ return true; });
    }

一些替代方法包括:

与在

  1. 中维护2个映射不同,复制原始映射并定义跟踪类型是否是关键字时执行验证的类型,为批量validation.
  2. ApplicationConfig提供了一种机制,可以扩展为允许调用者请求特定类型的数据,而不是提供对底层映射的访问。例如:将谓词传递给TypeStore的public <T> TypeStore<T> getData(Class<T> type)
  3. Instead,可以提供允许访问存储的已转换和未转换版本的Function (或者,TypeStore可以具有函数'transform‘,该函数返回由当前TypeStore支持的新类型的新TypeStore)
票数 0
EN

Stack Overflow用户

发布于 2020-09-18 05:46:59

“…此存储是应用程序…所需的最基本信息“

这意味着需要一个统一的抽象,比如…

代码语言:javascript
复制
public interface Storable< MBI > { 
    
    MBI getMinimumBasicInformation( );
}

“…“未检查的类型转换”让我认为有更好的方法来解决这个…“

好地方。unchecked warnings是一个标志,表明设计需要进行重构,以使其更加类型安全。…

代码语言:javascript
复制
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); }

}

和一个类型安全的实现(zero unchecked warnings)…

代码语言:javascript
复制
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( );
    }
}

然后是one of things that it stores ()…的示例

代码语言:javascript
复制
public class Foo implements Storable< Long > {
    
    protected Long id;
    
    @Override
    public Long getMinimumBasicInformation( ) { return this.id; }
}

我很可能会使用streams处理这些IRL。但由于这只是一个简单的实验,只是为了开…的玩笑

代码语言:javascript
复制
…
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 ) );
…
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63944572

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档