Hazelcast docs解释了当我们有Sys.setenv(http_proxy="http://corp.com:8080")
时如何执行此操作,但没有关于地图值是集合时的情况。
我看到两个选项:
IMap<String,Object>
包装成包装器类型,从而返回Set<Object>
,然后需要在本地过滤; 编辑:实施最终与mikhail-baksheev建议的类似。请注意,Set
使用ifblock来决定应收集CollectionExtractor
中的哪个字段。对此有没有更漂亮(但仍然有效)的解决方案?
MyObject
答案 0 :(得分:2)
例如,您要查询一些定义为参数集Set<Parameter>
的对象:
public class Parameter {
private String name;
private Object value;
public Parameter( String name, Object value ) {
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
public Object getValue() {
return value;
}
}
首先,为Parameters
实现ValueExtarcator:
public class ParameterExtractor extends ValueExtractor<Set<Parameter>, String> {
@Override
public void extract( Set<Parameter> parameters, String parameterName, ValueCollector collector ) {
for ( Parameter p : parameters ) {
if ( parameterName.equals( p.getName() ) ) {
collector.addObject( p.getValue() );
}
}
}
}
接下来,将ValueExtractor添加到自定义属性parameter
的地图配置中:
Config config = new Config( "my-instance" );
MapConfig mapConfig = new MapConfig( "map" );
mapConfig.addMapAttributeConfig( new MapAttributeConfig( "parameter", ParameterExtractor.class.getName() ) );
config.addMapConfig( mapConfig );
在地图中添加一些数据:
HazelcastInstance hzInstance = Hazelcast.getOrCreateHazelcastInstance( config );
IMap<String, Set<Parameter>> objectsMap = hzInstance.getMap( "map" );
objectsMap.put( "user1", ImmutableSet.of(
new Parameter( "type", "user" ),
new Parameter( "firstName", "Joe" ) ) );
现在,您可以使用方括号来查询具有指定Property的数据:
objectsMap.values( Predicates.and( Predicates.equal( "parameter[type]", "user" ), Predicates.equal( "parameter[firstName]", "Joe" ) ) );
方括号中的值为custom argument,此值将作为第二个参数传递给值提取器的extract
方法,并可用于查找所需的属性。
修改:如果您在具有已定义字段的集合中有特殊类型,例如您的示例中的MyObject
类,您可以为MyObject
的每个字段实现ValueExtractor,而不是使用自定义属性来查找所需的字段:
public class Field_1Extractor extends ValueExtractor<Set<MyObject>, String> {
@Override
public void extract(
final Set<MyObject> target,
final String argument,
final ValueCollector collector ) {
for ( final MyObject o : target ) {
collector.addObject( o.getField_1() );
}
}
}
编辑:您还可以使用ValueExtractor查找包含值集合中的特定元素的条目。例如,“any”谓词的提取器:list[any] == some value
:
public class ListValueExtractor extends ValueExtractor<List<String>, String> implements Serializable {
@Override
public void extract( List<String> listValues, String argument, ValueCollector collector ) {
if ( "any".equals( argument ) ) {
for ( String v : listValues ) {
collector.addObject( v );
}
}
}
}
使用:
public class Main {
public static void main( String[] args ) {
Config cfg = new Config();
MapConfig mapConfig = new MapConfig( "things" );
mapConfig.addMapAttributeConfig( new MapAttributeConfig( "list", ListValueExtractor.class.getName() ) );//register extractor for 'list'
cfg.addMapConfig( mapConfig );
HazelcastInstance instance = Hazelcast.newHazelcastInstance( cfg );
IMap<String, List<String>> mapThings = instance.getMap( "things" );
mapThings.put( "Joe", new ArrayList<String>() {{
add( "apple" );
add( "box" );
add( "laptop" );
}} );
mapThings.put( "Denis", new ArrayList<String>() {{
add( "apple" );
add( "pencil" );
add( "jacket" );
}} );
EntryObject e = new PredicateBuilder().getEntryObject();
Predicate withApple = Predicates.equal( "list[any]", "apple" );
Predicate withLaptop = Predicates.equal( "list[any]", "laptop" );
List<String> usersWithApple = mapThings.entrySet( withApple ).stream().map( Map.Entry::getKey ).collect( Collectors.toList() );
List<String> usersWithLaptop = mapThings.entrySet( withLaptop ).stream().map( Map.Entry::getKey ).collect( Collectors.toList() );
System.out.println( usersWithApple ); // [Joe, Denis]
System.out.println( usersWithLaptop ); // [Joe]
}
}
也许hazelcast有更方便的方式来搜索地图值集合,但我没有在文档中找到它