I'm very new to Groovy but I couldn't find an answer to my question over web.
I've a very simple map: Map<String, Object>. I need to update values of this map using a method while iterating. I've found a way to do it:
Map<String, Object> newMap = myMap.each { it -> it.value = getValue(it.key) }
I couldn't understand why this doesn't work:
Map<String, Object> newMap = myMap.each { k,v -> v = getValue(k) }
Thanks in advance.
If you know Java, then consider the code below as an crude approximation to what Groovy is doing. Be sure to examine the comment in the eachBlock regarding assignment to v
import java.util.*;
public class Mapper {
public void each(Map<String,Object> map) {
for (String k : map.keySet()) {
Object v = map.get(k);
eachBlock(k,v);
}
}
public void eachBlock(String k, Object v) {
System.out.println("k: " + k + " , v: " + v);
// assigning to v here is local, on the stack:
// v = new Integer(22);
}
public static void main(String... args) {
Map<String,Object> map = new HashMap<String,Object>();
map.put("abc", new Integer(99));
map.put("def", new Double(3.14d));
map.put("ijk", new ArrayList());
Mapper mapper = new Mapper();
mapper.each(map);
}
}
Related
Given an object like this:
Matcher matcher = pattern.matcher(sql);
with usage like so:
Set<String> matches = new HashSet<>();
while (matcher.find()) {
matches.add(matcher.group());
}
I'd like to replace this while loop by something more object-oriented like so:
new Iterator<String>() {
#Override
public boolean hasNext() {
return matcher.find();
}
#Override
public String next() {
return matcher.group();
}
}
so that I can easily e.g. make a Stream of matches, stick to using fluent APIs and such.
The thing is, I don't know and can't find a more concise way to create this Stream or Iterator. An anonymous class like above is too verbose for my taste.
I had hoped to find something like IteratorFactory.from(matcher::find, matcher::group) or StreamSupport.of(matcher::find, matcher::group) in the jdk, but so far no luck. I've no doubt libraries like apache commons or guava provide something for this, but let's say I can't use those.
Is there a convenient factory for Streams or Iterators that takes a hasNext/next method combo in the jdk?
In java-9 you could do it via:
Set<String> result = matcher.results()
.map(MatchResult::group)
.collect(Collectors.toSet());
System.out.println(result);
In java-8 you would need a back-port for this, taken from Holger's fabulous answer
EDIT
There is a single method btw tryAdvance that could incorporate find/group, something like this:
static class MyIterator extends AbstractSpliterator<String> {
private Matcher matcher;
public MyIterator(Matcher matcher) {
// I can't think of a better way to estimate the size here
// may be you can figure a better one here
super(matcher.regionEnd() - matcher.regionStart(), 0);
this.matcher = matcher;
}
#Override
public boolean tryAdvance(Consumer<? super String> action) {
while (matcher.find()) {
action.accept(matcher.group());
return true;
}
return false;
}
}
And usage for example:
Pattern p = Pattern.compile("\\d");
Matcher m = p.matcher("12345");
Set<String> result = StreamSupport.stream(new MyIterator(m), false)
.collect(Collectors.toSet());
This class I wrote embodies what I wanted to find in the jdk. Apparently though it just doesn't exist. eugene's accepted answer offers a java 9 Stream solution though.
public static class SearchingIterator<T> implements Iterator<T> {
private final BooleanSupplier advancer;
private final Supplier<T> getter;
private Optional<T> next;
public SearchingIterator(BooleanSupplier advancer, Supplier<T> getter) {
this.advancer = advancer;
this.getter = getter;
search();
}
private void search() {
boolean hasNext = advancer.getAsBoolean();
next = hasNext ? Optional.of(getter.get()) : Optional.empty();
}
#Override
public boolean hasNext() {
return next.isPresent();
}
#Override
public T next() {
T current = next.orElseThrow(IllegalStateException::new);
search();
return current;
}
}
Usage:
Matcher matcher = Pattern.compile("\\d").matcher("123");
Iterator<String> it = new SearchingIterator<>(matcher::find, matcher::group);
I have following error in this code: Cannot infer type arguments for ReadOnlyListWrapper<>
How should my return type look like? I need to save arraylist for each node in all columns. But I can not return it.
for (Entry<String, String> ent : dc.getSortedOrgAll().entrySet()) {
TreeTableColumn<String, ArrayList<String>> col = new TreeTableColumn<>(
ent.getValue());
col.setCellValueFactory(new Callback<TreeTableColumn.CellDataFeatures<String, ArrayList<String>>, ObservableValue<ArrayList<String>>>() {
#Override
public ObservableValue<ArrayList<String>> call(
CellDataFeatures<String, ArrayList<String>> param) {
TreeMap<String, List<String>> temp = (TreeMap<String, List<String>>) dc
.getFuncTypeOrg().clone();
ArrayList<String> result = new ArrayList<>();
for (int i = 0; i < temp.size(); i++) {
List<String> list = temp.firstEntry().getValue();
String key = temp.firstEntry().getKey();
// root.getChildren();
if (list.get(1).equals("Papier")) {
System.out.println(list.get(1));
}
if (list.get(1).equals(param.getValue().getValue())
&& list.get(5).equals(col.getText())) {
result.add(list.get(2));
if(list.size()==9)
result.add(list.get(list.size()-1));
else result.add("White");
} else {
temp.remove(key);
// result = null;
}
}
return new ReadOnlyListWrapper<>(result);
}
});
ReadOnlyListWrapper<T> implements ObservableValue<ObservableList<T>>, which isn't what you need, as you declared the callback to return an ObservableValue<ArrayList<T>> (T is just String here).
So I think you just need
return new ReadOnlyObjectWrapper<ArrayList<String>>(result);
and you can probably omit the generic type:
return new ReadOnlyObjectWrapper<>(result);
Just a comment: I think you could make your life much easier by defining some actual data model classes, instead of trying to force your data into various collections implementations.
I have been looking through java's api of Map for possible reason why a certain Map (map1) in my code gets updated as well when I update another map (map2) or maybe something is wrong about how I wrote it.
void process(Object superObject) {
Map<Date, Object> map1 = superObject.getValuesForMap();
Map<Date, Object> map2 = map1;
updateValueOf(superObject,map2);
}
This is how I updated the value of map2.
updateValueOfMap(Object superObject,Map<Date, Object> map2){
List<Object> objects = getTheObjectsFromASource;
for (Object obj : objects) {
List<Triple<Date, Double, Object>> triples = superObject.getSomeEntriesWithThisAttribute(obj.getCertainAttrib());
for (Triple<D,D,O> t : triples) {
Object cache = map2.get(t.first)
if (cache == null) {
cache = new Object();
cache.setThis(t.second);
cache.setThat(t.third);
} else {
Double value = cache.getThis() + t.second; // add the double value from triple to the current cache Object's value
cache.setThis(value); // and update the Object's value in the map
}
map2.put(t.first, cache);
}
}
}
The problem is certain entries in superObject.getValuesForMap() gets updated too with the same value as the corresponding entries in map2 every iteration in the for (Triple..). Why is that so?
Responses will be greatly appreciated. Thanks in advance!
Map map1 = superObject.getValuesForMap();
Map map2 = map1;
All three above , points to the same memory location, so it will indeed be updated.
Try this way :
Map map2 = new HashMap();
map2.putAll(map1);
UPDATE : Sample program below(map1 not updated with MAP2 changes.)
public class BaseClass {
Map<String,String> xx = new HashMap<String,String>();
public BaseClass(){
xx.put("1", "One");
xx.put("2", "Two");
xx.put("3", "Three");
}
public Map<String,String> getValuesForMap(){
return xx;
}
}
public class TestProgram extends BaseClass{
void process() {
Map<String, String> map1 = getValuesForMap();
Map<String, String> map2 = new HashMap<String,String>();
map2.putAll(map1);
updateValueOf(map1, map2);
}
public void updateValueOf(Map<String, String> map1, Map<String, String> map2){
String str1 = map2.get("1");
str1 = str1+"Item";
map2.put("1", str1);
String str2 = map2.get("2");
str2 = str2+"Item";
map2.put("2", str2);
String str3 = map2.get("3");
str3 = str3+"Item";
map2.put("3", str3);
System.out.println("Printing Map1 ");
printit(map1);
System.out.println("Printing Map2 ");
printit(map2);
System.out.println("Printing Map1 Again");
printit(map1);
System.out.println("Printing Map2 Again");
printit(map2);
}
public void printit(Map<String,String> map){
Iterator iter = map.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry pairs = (Map.Entry)iter.next();
System.out.println(pairs.getKey() + " = " + pairs.getValue());
}
}
public static void main(String[] args){
TestProgram ts = new TestProgram();
ts.process();
}
}
I want to automate the Setup code by a given array containing expected result and parameters.
Something like data driven setup.
My existing code:
var mock = new Mock<ILogin>();
var testDataTable = new object[,]
{
{ LoginResult.Success, "Jack", "123!##"}
, { LoginResult.WrongPassword, "Jack", "123321"}
, { LoginResult.NoSuchUser, "Peter", "123!##"}
};
// ForEachRow is my own extension method
testDataTable.ForEachRow((row) =>
{
var result = (LoginResult)row[0];
var username = (string)row[1];
var password = (string)row[2];
mock.Setup(o => o.Login(
It.Is<string>(u => u == username),
It.Is<string>(p => p == password)
)).Returns(result);
});
return mock.Object;
Code that I wish:
var mock = new Mock<ILogin>();
new object[,]
{
{ LoginResult.Success, "Jack", "123!##"}
, { LoginResult.WrongPassword, "Jack", "123321"}
, { LoginResult.NoSuchUser, "Peter", "123!##"}
}.ForEachRow((row) =>
{
var exprTree = (ILogin o)=>o.Login("ANY", "ANY");
AutoSetup(mock, exprTree, row); // <---- How to write this AutoSetup?
});
return mock.Object;
How to write the AutoSetup(mock, exprTree, dataArray) function above?
It takes three parameters:
mock: A mock object, e.g. new Mock()
exprTree: Expression tree that represents a method to be setup
dataArray: An object[], the 0 element is the expected result, and others are parameters that passed to the method
This was an interesting challenge. I think I have a working implementation for your AutoSetup method, using the expressions API. If anyone has a simpler solution, I'd love to see it.
static void AutoSetup<TMock, TResult>(Mock<TMock> mock, Expression<Func<TMock, TResult>> exprTree, object[] items) where TMock : class
{
var methodCallExpr = exprTree.Body as MethodCallExpression;
var arguments = items.Skip(1).Select(o => Expression.Constant(o));
var updatedMethod = methodCallExpr.Update(methodCallExpr.Object, arguments);
var updatedLambda = exprTree.Update(updatedMethod, exprTree.Parameters);
mock.Setup(updatedLambda).Returns((TResult)items[0]);
}
Here is a full working test as a console app, with an implementation of ForEachRow, which you didn't provide.
class Program
{
static void Main(string[] args)
{
var login = SetUp();
Console.WriteLine(login.Login("Jack", "123!##"));
Console.WriteLine(login.Login("Jack", "123321"));
Console.WriteLine(login.Login("Peter", "123!##"));
Console.ReadKey();
}
static ILogin SetUp()
{
var mock = new Mock<ILogin>(MockBehavior.Strict);
var rows = new object[,]
{
{ LoginResult.Success, "Jack", "123!##" },
{ LoginResult.WrongPassword, "Jack", "123321" },
{ LoginResult.NoSuchUser, "Peter", "123!##" }
};
rows.ForEachRow((row) => AutoSetup(mock, (ILogin l) => l.Login("ANY", "ANY"), row));
return mock.Object;
}
private static void AutoSetup<TMock, TResult>(Mock<TMock> mock, Expression<Func<TMock, TResult>> exprTree, object[] items) where TMock : class
{
var methodCallExpr = exprTree.Body as MethodCallExpression;
var arguments = items.Skip(1).Select(o => Expression.Constant(o));
var updatedMethod = methodCallExpr.Update(methodCallExpr.Object, arguments);
var updatedLambda = exprTree.Update(updatedMethod, exprTree.Parameters);
mock.Setup(updatedLambda).Returns((TResult)items[0]);
}
}
public static class ArrayExtensions
{
public static void ForEachRow<T>(this T[,] rows, Action<T[]> action)
{
var x = rows.GetLength(1);
var y = rows.GetLength(0);
for (int i = 0; i < y; i++)
{
var row = new T[x];
for (int j = 0; j < x; j++)
{
row[j] = rows[i, j];
}
action(row);
}
}
}
public interface ILogin
{
LoginResult Login(string p1, string p2);
}
public enum LoginResult
{
Success,
WrongPassword,
NoSuchUser
}
EDIT: You asked in a comment about how to take advantage of the variable parameter matching that Moq provides with the It.IsAny<> method. Because what you pass to your Mock.Setup() is an expression tree, it's able to scan the method parameters and implement special behaviour for any that are calls to It.IsAny<>. However, if you use It.IsAny<> in your test data array, by the time we retrieve it from your items array to set in on the expression, it's not a method call but simply the result of the call it It.IsAny<> which is default(T) (see here).
We need some way of specifying in your test data array that the parameter should be any. Then we can check for this special case and generate the correct MethodCallExpression representing a call to It.IsAny<>.
Here are the changes I made to support this:
Add an Any type to use in your test data
public class Any<T>
{
private Any() { }
public static Any<T> Param { get { return new Any<T>(); } }
}
Update the AutoSetup method to handle this special case:
private static void AutoSetup<TMock, TResult>(Mock<TMock> mock, Expression<Func<TMock, TResult>> exprTree, object[] items) where TMock : class
{
var arguments = items.Skip(1).Select(o => {
var type = o.GetType();
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Any<>))
{
var typeParameter = type.GetGenericArguments();
var genericItIsAny = typeof(It).GetMethod("IsAny");
var itIsAny = genericItIsAny.MakeGenericMethod(typeParameter);
return Expression.Call(itIsAny) as Expression;
}
return Expression.Constant(o);
});
var methodCallExpr = exprTree.Body as MethodCallExpression;
var updatedMethod = methodCallExpr.Update(methodCallExpr.Object, arguments);
var updatedLambda = exprTree.Update(updatedMethod, exprTree.Parameters);
mock.Setup(updatedLambda).Returns((TResult)items[0]);
}
In the test data, use the Any type
{ LoginResult.Success, "NoPasswordUser", Any<string>.Param }
Depending on how you're storing your test data, you might need another way of identifying parameters that you want to be variable (specially formatted string?), but in general this should give you an idea about how to create the correct expressions.
I am writing a Metro App.
I am trying to read a file and return a float[] from the data. But no matter what I do, the function seems to return null. I have tried the solutions to similar questions to no luck.
For example if I use:
float[] floatArray = new ModelReader("filename.txt").ReadModel()
The result will be a null array.
However if I use:
new ModelReader("filename.txt")
The correct array will be printed to the console because "Test" also prints the array before returning it. This seems very weird to me.
Please give me some guidance, I have no idea what is wrong.
public class ModelReader
{
float[] array;
public ModelReader(String name)
{
ReadModelAsync(name);
}
public float[] ReadModel()
{
return array;
}
private async Task ReadModelAsync(String name)
{
await readFile(name);
}
async Task readFile(String name)
{
// settings
var path = #"Assets\models\" + name;
var folder = Windows.ApplicationModel.Package.Current.InstalledLocation;
// acquire file
var file = await folder.GetFileAsync(path);
// read content
var read = await Windows.Storage.FileIO.ReadTextAsync(file);
using (StringReader sr = new StringReader(read))
{
Test test = new Test(getFloatArray(sr));
this.array = test.printArray();
}
}
private float[] getFloatArray(StringReader sr) { ... }
public class Test
{
public float[] floatArray;
public Test(float[] floatArray)
{
this.floatArray = floatArray;
}
public float[] printArray()
{
for (int i = 0; i < floatArray.Length; i++)
{
Debug.WriteLine(floatArray[i]);
}
return floatArray;
}
}
You're trying to get the result of an asynchronous operation before it has completed. I recommend you read my intro to async / await and follow-up with the async / await FAQ.
In particular, your constructor:
public ModelReader(String name)
{
ReadModelAsync(name);
}
is returning before ReadModelAsync is complete. Since constructors cannot be asynchronous, I recommend you use an asynchronous factory or asynchronous lazy initialization as described on my blog (also available in my AsyncEx library).
Here's a simple example using an asynchronous factory approach:
public class ModelReader
{
float[] array;
private ModelReader()
{
}
public static async Task<ModelReader> Create(string name)
{
var ret = new ModelReader();
await ret.ReadModelAsync(name);
return ret;
}
...
}