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();
}
}
Related
I would like to evaluate a CSV data series with Xunit.
For this I need to read in a string consisting of int, bool, double and others.
With the following code, the transfer basically works for one row.
But since I want to test for predecessor values, I need a whole CSV file for evaluation.
My [Theory] works with InlineData without errors.
But when I read in a CSV file, the CSVDataHandler gives a System.ArgumentOutOfRangeException!
I can't find a solution for the error and ask for support.
Thanks a lot!
[Theory, CSVDataHandler(false, "C:\\MyTestData.txt", Skip = "")]
public void TestData(int[] newLine, int[] GetInt, bool[] GetBool)
{
for (int i = 0; i < newLine.Length; i++)
{
output.WriteLine("newLine {0}", newLine[i]);
output.WriteLine("GetInt {0}", GetInt[i]);
output.WriteLine("GetBool {0}", GetBool[i]);
}
}
[DataDiscoverer("Xunit.Sdk.DataDiscoverer", "xunit.core")]
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public abstract class DataArribute : Attribute
{
public abstract IEnumerable<object> GetData(MethodInfo methodInfo);
public virtual string? Skip { get; set; }
}
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class CSVDataHandler : DataAttribute
{
public CSVDataHandler(bool hasHeaders, string pathCSV)
{
this.hasHeaders = hasHeaders;
this.pathCSV = pathCSV;
}
public override IEnumerable<object[]> GetData(MethodInfo methodInfo)
{
var methodParameters = methodInfo.GetParameters();
var paramterTypes = methodParameters.Select(p => p.ParameterType).ToArray();
using (var streamReader = new StreamReader(pathCSV))
{
if (hasHeaders) { streamReader.ReadLine(); }
string csvLine = string.Empty;
// ReadLine ++
//while ((csvLine = streamReader.ReadLine()) != null)
//{
// var csvRow = csvLine.Split(',');
// yield return ConvertCsv((object[])csvRow, paramterTypes);
//}
// ReadToEnd ??
while ((csvLine = streamReader.ReadToEnd()) != null)
{
if (Environment.NewLine != null)
{
var csvRow = csvLine.Split(',');
yield return ConvertCsv((object[])csvRow, paramterTypes); // System.ArgumentOutOfRangeException
}
}
}
}
private static object[] ConvertCsv(IReadOnlyList<object> cswRow, IReadOnlyList<Type> parameterTypes)
{
var convertedObject = new object[parameterTypes.Count];
for (int i = 0; i < parameterTypes.Count; i++)
{
convertedObject[i] = (parameterTypes[i] == typeof(int)) ? Convert.ToInt32(cswRow[i]) : cswRow[i]; // System.ArgumentOutOfRangeException
convertedObject[i] = (parameterTypes[i] == typeof(double)) ? Convert.ToDouble(cswRow[i]) : cswRow[i];
convertedObject[i] = (parameterTypes[i] == typeof(bool)) ? Convert.ToBoolean(cswRow[i]) : cswRow[i];
}
return convertedObject;
}
}
MyTestData.txt
1,2,true,
2,3,false,
3,10,true,
The first call to streamReader.ReadToEnd() will return the entire contents of the file in a string, not just one line. When you call csvLine.Split(',') you will get an array of 12 elements.
The second call to streamReader.ReadToEnd() will not return null as your while statement appears to expect, but an empty string. See the docu at
https://learn.microsoft.com/en-us/dotnet/api/system.io.streamreader.readtoend?view=net-7.0
If the current position is at the end of the stream, returns an empty
string ("").
With the empty string, the call to call csvLine.Split(',') will return an array of length 0, which causes your exception when its first element (index 0) is accessed.
All of this could have been easily discovered by simply starting the test in a debugger.
It looks like you have some other issues here as well.
I don't understand what your if (Environment.NewLine != null) is intended to do, the NewLine property will never be null but should have one of the values "\r\n" or "\n" so the if will always be taken.
The parameters of your test method are arrays int[] and bool[], but you are checking against the types int, double and bool in your ConvertCsv method, so the alternative cswRow[i] will always be returned. You'll wind up passing strings to your method expecting int[] and bool[] and will at latest get an error there.
This method reads a data series from several rows and columns and returns it as an array for testing purposes.
The conversion of the columns can be adjusted according to existing pattern.
Thanks to Christopher!
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class CSVDataHandler : Xunit.Sdk.DataAttribute
{
public CSVDataHandler(string pathCSV)
{
this.pathCSV = pathCSV;
}
public override IEnumerable<object[]> GetData(MethodInfo methodInfo)
{
List<int> newLine = new();
List<int> GetInt = new();
List<bool> GetBool = new();
var reader = new StreamReader(pathCSV);
string readData = string.Empty;
while ((readData = reader.ReadLine()) != null)
{
string[] split = readData.Split(new char[] { ',' });
newLine.Add(int.Parse(split[0]));
GetInt.Add(int.Parse(split[1]));
GetBool.Add(bool.Parse(split[2]));
// Add more objects ...
}
yield return new object[] { newLine.ToArray(), GetInt.ToArray(), GetBool.ToArray() };
}
}
Trying to get a count of records in the Stream for a time window of 5s. Always getting a count of 1 ??
Sent in 10 records.Expect the count to be 10 at the end.
Tried to follow the advise here from Fabian Hueske- How to count the number of records processed by Apache Flink in a given time window
DataStream<Map<String, Object>> kinesisStream;
...//get data from Kinesis source into kinesisStream - works fine
final SingleOutputStreamOperator<Map<String, Object>> filterDroppedEvents = kinesisStream
.filter(resultMap -> {
long timestamp = Utils.getEventTimestampFromMap(resultMap);
long currTimestamp = System.currentTimeMillis();
long driftFromCurrTS = currTimestamp - timestamp;
if (driftFromCurrTS < 0) {
Object eventNameObj = resultMap.get(EVENT_NAME);
String eventName = eventNameObj != null ? (String) eventNameObj : "";
logger.debug("PMS - event_timestamp is > current timestamp by driftFromCurrTS:{} for event_name:{} and event_timestamp:{}", driftFromCurrTS, eventName, timestamp);
return true;
} else {
return false;
}
});//called 10 times here - GOOD
final SingleOutputStreamOperator<CountRows> droppedEventsMapToCountRows = filterDroppedEvents
.map(mapValue -> new CountRows(mapValue, 1L, mapValue.get(EVENT_NAME) != null ? (String) mapValue.get(EVENT_NAME) : ""));//this is called 10 times - GOOD
final KeyedStream<CountRows, String> countRowsKeyedStream = droppedEventsMapToCountRows.keyBy(new KeySelector<CountRows, String>() {
#Override
public String getKey(CountRows countRows) throws Exception {
logger.info("Inside getKey");
return countRows.getEventName();
}
});//doesn't get in here to this logger statement ??
final AllWindowedStream<CountRows, TimeWindow> countRowsTimeWindowAllWindowedStream = countRowsKeyedStream
.timeWindowAll(org.apache.flink.streaming.api.windowing.time.Time.seconds(5));
//.sum("count")
final SingleOutputStreamOperator<CountRows> countRowsReduceStream = countRowsTimeWindowAllWindowedStream.reduce((accum, input) -> {
logger.info("Inside reduce");
return new CountRows(input.getRow(), accum.getCount() + input.getCount(), input.getEventName());// sum 1s to count
});//don't see this logger statement "Inside reduce"
DataStream<InfluxDBPoint> droppedEventsStream =
countRowsReduceStream.flatMap(new FlatMapFunction<CountRows, InfluxDBPoint>() {
#Override
public void flatMap(CountRows countRows, Collector<InfluxDBPoint> out) throws Exception {
logger.info("Inside final map"); // only called once and countRows.getCount() is 1 - BAD - want it to be 10 ??
Map<String, Object> mapValue = countRows.getRow();
//long currTimestamp = System.currentTimeMillis();
Object eventTSObj = mapValue.get(EVENT_TIMESTAMP);
String eventTimestamp = eventTSObj != null ? (String)eventTSObj : "";
long eventTS = Utils.getLongFromDateStr(eventTimestamp);
Map<String, String> tags = new HashMap<>();
Object eventNameObj = mapValue.get(Utils.EVENT_NAME);
String eventName = eventNameObj != null ? (String)eventNameObj : "";
tags.put(Utils.EVENT_NAME, eventName);
Map<String, Object> fields = new HashMap<>();
fields.put("count", countRows.getCount());
out.collect(new InfluxDBPoint("dropped_events_count", eventTS, tags, fields));//TODO: measurement name
}
});
/* Tried map but doesn't work
reduceStream.map(countRows -> {
logger.info("Inside final map");
Map<String, Object> mapValue = countRows.getRow();
//long currTimestamp = System.currentTimeMillis();
Object eventTSObj = mapValue.get(EVENT_TIMESTAMP);
String eventTimestamp = eventTSObj != null ? (String)eventTSObj : "";
long eventTS = Utils.getLongFromDateStr(eventTimestamp);
Map<String, String> tags = new HashMap<>();
Object eventNameObj = mapValue.get(Utils.EVENT_NAME);
String eventName = eventNameObj != null ? (String)eventNameObj : "";
tags.put(Utils.EVENT_NAME, eventName);
Map<String, Object> fields = new HashMap<>();
fields.put("count", countRows.getCount());
return new InfluxDBPoint("dropped_events_count", eventTS, tags, fields);//TODO: measurement name
});*/
droppedEventsStream.addSink(influxSink);
#############################
CountRows is a POJO wrapper around the Map<String, Object> to add the count:
public static class CountRows implements Serializable, Comparable<CountRows> {
Map<String, Object> row;
Long count;
String eventName;
//default constructor and constructor with 3 attributes
.........
TIA,
One thing that stands out is that you are using timeWindowAll with a KeyedStream. This is not how this part of the API should be used. If you wish to compute a global count across all of the keys, then remove the keyBy; if you wish to count the events for each key separately, then keep the keyBy and use timeWindow rather than timeWindowAll.
I also see that you have event time timestamps, but don't appear to be using event time windows (since I don't see a timestamp assigner or watermark generator). I can't tell if that's intentional, or possibly related to why the results don't match your expectations.
I have a class called Result (data that I want to show in my table) with several attributes.
public class Result
{
private final SimpleStringProperty object;
private List<SimpleStringProperty> listObject= new ArrayList<SimpleStringProperty>();
private final Util util = new Util();
public Result(String object, String[] listObject)
{
this.object= new SimpleStringProperty(object);
this.objectList= util.transformar(listObject);
}
public String getObject()
{
return this.object.get();
}
public void setObject(String object)
{
this.hash.set(hash);
}
public String[] getListObject()
{
return util.transformar2(this.listObject);
}
public void setListObject(String[] listObject)
{
this.listObject= transformar(listObject);
}
}
And I have my controller where I have an empty table and I add the columns and the objetcs Result. The controller has the attribute:
#FXML
private TableView tablaResultado;
The method were I do that is:
private List<TableColumn> load()
{
List<TableColumn> listColumn = new ArrayList<TableColumn>();
Object2 object2= new Object2();
List<Result> listaResultado = object2.getResultado();
ObservableList<Result> prueba = FXCollections
.observableArrayList(listaResultado);
TableColumn<Result, String> object= new TableColumn<Result, String>("object");
direccion.setCellValueFactory(
new PropertyValueFactory<Result, String>(
"object"));
listColumn.add(object);
List<TableColumn<Result, String>> listObject = new ArrayList<TableColumn<Result, String>>();
for (int i = 0; i < ((Result) listaResultado
.get(0)).getListObject().length; i++)
{
TableColumn<Result, String> columna = new TableColumn<Result, String>(
this.lenguaje.getProperty("listObject"+i);
columna.setCellValueFactory(
new PropertyValueFactory<Result, String>(
"listObject[" + i + "]"));
objectList.add(columna);
}
listColumn.addAll(objectList);
ObservableList<TableColumn<Result, String>> prueba2 = FXCollections
.observableArrayList(listObject);
this.tablaResultado.setItems(prueba);
this.tablaResultado.getColumns().addAll(object);
for (int i = 0; i < prueba2.size(); i++)
{
this.tablaResultado.getColumns().addAll(prueba2.get(i));
}
}
return listColumn ;
The result is the columns with their names and the data in the column object but the data in the columns listObject is empty. It has to be a list or something because I don't know the size of listObject.
If I change:
columna.setCellValueFactory(new PropertyValueFactory<Result, String ("listObject[" + i + "]"));
and I write:
columna.setCellValueFactory(new PropertyValueFactory<Result, String ("listObject"));
I got something like Ljava.lang.String;#bda3303 in that columns.
Do
final int index = i ;
columna.setCellValueFactory(cellData ->
new SimpleStringProperty(cellData.getValue().getListObject()[index]));
PropertyValueFactory does not "evaluate" an expression. It just tries to access a property of the table item. The default TableCells will use the toString method to get the text to display, which is why you get something like Ljava.lang.String;#bda3303 in the third version, see Java arrays printing out weird numbers, and text .
However you can write your own cellValueFactory:
public class Result
public StringProperty listObjectProperty(int index) {
return listObject.get(index);
}
final int columnIndex = i;
columna.setCellValueFactory(cellData -> cellData.getValue().listObjectProperty(columnIndex));
Alternatively simply create a ObservableValue<String> with a constant value for the column value:
final int columnIndex = i;
columna.setCellValueFactory(cellData -> Bindings.createStringBinding(() -> cellData.getValue().getListObject()[columnIndex]));
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'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);
}
}