Looking at the documentation, it seems like I could use either a ListState or a ValueState<List<String>> to store state. For example the code below:
// Use ListState
ListStateDescriptor<String> lDescriptor = new ListStateDescriptor<String>
("testListState", TypeInformation.of(new TypeHint<String>() {}));
ListState<String> testListState = getRuntimeContext().getListState(lDescriptor);
// Use ValueState
ValueStateDescriptor<List<String>> testDescriptor =
new ValueStateDescriptor<List<String>>("testList",
TypeInformation.of(new TypeHint<List<String>>() {}));
ValueState<List<String>> testState = getRuntimeContext().getState(testDescriptor);
If I need to store a unique list of elements tied to each key, would there be a benefit of using one over the other? The downside of using ListState would be first converting the Iterable to a List<> if I need to modify it before saving the list whereas I could just retrieve the list directly if I use ValueState.
I only use ValueState if I only want store one value to each key. You can use it to store lists, but the code will be more verbose.
If you use ValueState, you must get the value, update the list, and update the value but if you use ListState you can manage it directly
Related
In my hazelcast jet application I am performing grouping joins after that I am getting result in
BatchStage<List> format but I want to convert it to BatchStage, I have tried flatMap but it overwrites some keys that I don't want I want all Object to be stored individually.
My Code:
BatchStage<Object> bd = jdbcBatchStageData.flatMap(list -> Traversers.traverseArray(list.toArray()));
I know flatMap will replace some keys but How can I store all Object individually in BatchStage so they don't get override any keys.
Object is equal to Map<String, Object>.
Depending on the form of your data (which you don't provide), here's a proposal that might need some tweaking:
jdbcBatchStageData.flatMap(list -> Traversers.traverseArray(list.toArray()))
.groupingKey(ByKey)
.aggregate(AggregateOperations.toList())
Flat maps the different lists into individual items
Group by key (you need to define ByKey function`
Aggregate the result, so you'd a batch of Map.Entry<K, List>
If I run the code below, the value coming from getUserName() gets appended to the list. But if I run it again, same value gets inserted again. My question is, how to make sure the value is appended only once(Unique)?
My current code
Operation operation = ListOperation.append("names", Value.get(usr.getUserName()));
Record record = client.operate( policy, key, operation );
Example: Consider the "name" bin to be a list of strings.
'LIST["T1", "T2"]'
If I add T2 again, the list should remain the same.
ListOperation.append() can take a ListPolicy, which takes flags. For write operations such as this, the ListWriteFlags have the fields ADD_UNIQUE and NO_FAIL which you should combine if you want a value to only be added if it's a new unique list element.
See https://www.slideshare.net/RonenBotzer/asug-tlvmeetup2talk
i'm assuming that ListOperation is backed by a List since the code isn't available. Assuming it is, Lists maintain order while allowing null values. Sets on the other hand only allow unique, non-null, values so this would be a perfect solution for you.
Set<String> values = new HashSet<>();
values.add("T1");
values.add("T1"); // already contains value
Alternative
If you need to maintain the order of your Collection but you want unique values, another option would be to check on add if the value already exists OR using Stream#distinct.
List<String> values = ListOperation.values.stream().distinct().collect(Collectors.toList());
Long story short, I am using JDBI DAO to access data. It is hard to have a query with a dynamic order in it. So I am planning to use a Java 8 stream to perform this as a post processing step after the query results are fetched.
The problem is the way the comparator works by having to declare a method of the object statically.
shepherds = shepherds.stream()
.sorted(Comparator.comparing(Shepherd::getId).reversed())
.collect(Collectors.toList());
How can I do this dynamically with what will be variables like this
orderBy = id
orderDirection = ASC
So that I can paramaterize this method call?
e.g.
if(orderDirection.equals("ASC"))
shepherds.stream().sorted(Comparator.comparing(orderBy));
else
shepherds.stream().sorted(Comparator.comparing(orderBy).reversed());
The simplest way is to probably build a Map (unless you really can't do that on the DB side, which should be your main focus), where the Key would look like :
class Key {
String field;
Direction direction; // enum
// getters/setters/hashcode/equals
}
And simply create this Map upfront:
Map<Key, Comparator<Shepherd>> map = new HashMap<>();
map.put(new Key("id", Direction.ASC), Comparator.comparing(Shepard::getId))
map.put(new Key("id", Direction.DESC), Comparator.comparing(Shepard::getId).reversed())
The other way, I think it would be possible to create this really dynamically via LambdaMetafactory, but it is rather complicated.
I have RealmResults that I receive from Realm like
RealmResults<StepEntry> stepEntryResults = realm.where(StepEntry.class).findAll();
Now I want convert RealmResults<StepEntry> to ArrayList<StepEntry>
I have try
ArrayList<StepEntry> stepEntryArray = new ArrayList<StepEntry>(stepEntryResults));
but the item in my ArrayList is not my StepEntry object, it is StepEntryRealmProxy
How can I convert it?
Any help or suggestion would be great appreciated.
To eagerly read every element from the Realm (and therefore make all elements in the list become unmanaged, you can do):
List<StepEntry> arrayListOfUnmanagedObjects = realm.copyFromRealm(realmResults);
But you generally have absolutely no reason to do that unless you want to serialize the objects with GSON (specifically, because it reads field data with reflection rather than with getters), because Realm was designed in such a way that the list exposes a change listener, allowing you to keep your UI up to date just by observing changes made to the database.
The answer by #EpicPandaForce works well. I tried this way to optimize my app performance and I find the following is a bit faster. Another option for people who prefer speed:
RealmResults<Tag> childList = realm.where(Tag.class).equalTo("parentID", id).findAll();
Tag[] childs = new Tag[childList.size()];
childList.toArray(childs);
return Arrays.asList(childs);
In Kotlin:
var list : List<Student>: listof()
val rl = realm.where(Student::class.java).findAll()
// subList return all data contain on RealmResults
list = rl.subList(0,rl.size)
I have a MultiValueMap like
{3=[c-2, c-2], 2=[b-1, b-1], 1=[a-1, a-2, a-3]}
At one point I have to update a single value of a specific key
for example I have to update the key 2 like
2=[u-1,u-2]
how can i do this?
I've never used that library - but I would expect these two examples to do what you need:
multiMap.getCollection(2).clear();
multiMap.putAll(2, Arrays.asList("u-1", "u-2"));
Or
Collection c = multiMap.getCollection(2);
c.clear();
Collections.addAll(c, "u-1", "u-2");
The safest way is to call getCollection() to retrieve the current mapping, remove(key) to clear that mapping, iterate the retrieved collection to re-insert values that you want to keep, and/or add the new values.
If you know the type of collection used for a mapping (because you've called the constructor that takes collectionFactory), you could get the collection and update it directly.