Issue
This Content is from Stack Overflow. Question asked by Dorian Feyerer
Brief description:
Basically, inside my code i want to add a List <String>
to every <key>
inside a ListValuedMap <String, List<String>>
as a <value>
. I did some testing on the created ListValuedMap spreadNormal
with
System.out.println(spreadNormal.keySet());
System.out.println(spreadNormal.values());
and it showed me, that the keys are inside the map (unsorted), but the corresponding values are empty.
I am deleting the inserted List <String>
after using Collections.addAll(String, List<String>)
with list.clear()
after each loop.
I would have expected, that indeed a copy of these values stay in my ListValuedMap
but my results are:
[Agios Pharmaceuticals Inc., Vicor Corp., EDP Renov�veis S.A., Envista Holdings Corp., JENOPTIK AG,...]
[[], [], [], [], [], ...]
Can you provide some explanations on that? Is the default behaviour of the Collections.addAll
method to copy the reference to an object, instead of the object itself?
The corresponding code section is highlighted with // ++++++++++
Full code example (Eclipse):
import java.io.*;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import java.util.*;
import org.apache.commons.collections4.ListValuedMap;
import org.apache.commons.collections4.MultiSet;
import org.apache.commons.collections4.multimap.ArrayListValuedHashMap;
public class Webdata {
public static void main(String[] args) throws IOException
{
long start = System.currentTimeMillis();
parseData();
System.out.println(secondsElapsed(start)+" seconds processing time");
};
private static void parseData() throws IOException
{
List <String> subdirectories = new ArrayList<>();
String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
String errorMessage1 = "String formatting problem";
String errorMessage2 = "String object non existent";
for (int i=0; i< chars.length(); i++)
{
subdirectories.add("https://www.tradegate.de/indizes.php?buchstabe="+chars.charAt(i));
}
List <String> stockMetadata = new ArrayList<>();
ListValuedMap <String, List<String>> nonError = new ArrayListValuedHashMap<>();
ListValuedMap <String, List<String>> numFormatError = new ArrayListValuedHashMap<>();
ListValuedMap <String, List<String>> nullPointerError = new ArrayListValuedHashMap<>();
ListValuedMap <String, List<String>> spreadTooHigh = new ArrayListValuedHashMap<>();
ListValuedMap <String, List<String>> spreadNormal = new ArrayListValuedHashMap<>();
int cap1 = 44;
int cap2 = 56;
for (int suffix = 0; suffix <chars.length(); suffix++)
{
Document doc = Jsoup.connect(subdirectories.get(suffix).toString()).get();
Elements htmlTableRows = doc.getElementById("kursliste_abc").select("tr");
htmlTableRows.forEach( tr->
{
String stockName = tr.child(0).text();
String bid_price = tr.child(1).text();
String ask_price = tr.child(2).text();
String isin = tr.child(0).selectFirst("a").absUrl("href").substring(cap1,cap2);
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
try
{
if (calcSpread(bid_price, ask_price) < 5)
{
Collections.addAll(stockMetadata, isin, bid_price, ask_price, calcSpread(bid_price, ask_price).toString());
spreadNormal.put(stockName,stockMetadata);
}
else if (calcSpread(bid_price, ask_price) > 5)
{
Collections.addAll(stockMetadata, isin, bid_price, ask_price, calcSpread(bid_price, ask_price).toString());
spreadTooHigh.put(stockName,stockMetadata);
}
stockMetadata.clear();
}
catch (NumberFormatException e)
{
Collections.addAll(stockMetadata, e.getMessage());
numFormatError.put(stockName, stockMetadata);
stockMetadata.clear();
}
catch (NullPointerException Ne)
{
Collections.addAll(stockMetadata, Ne.getMessage());
nullPointerError.put(stockName, stockMetadata);
stockMetadata.clear();
} //end of try-catch
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
}); //end of for-each loop htmlTableRows
} //end of JSOUP method
System.out.println(spreadNormal.keySet());
System.out.println(spreadNormal.values());
} //end of parseData()
public static Float calcSpread (String arg1, String arg2)
{
try
{
Float bid = Float.parseFloat(arg1.replace("," , "."));
Float ask = Float.parseFloat(arg2.replace("," , "."));
Float spread = ((ask-bid)/ask)*100;
return spread;
}
catch (NumberFormatException e)
{
return null;
}
}
public static Long secondsElapsed(Long start) {
Long startTime = start;
Long endTime = System.currentTimeMillis();
Long timeDifference = endTime - startTime;
return timeDifference / 1000;
}
} //end of class
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>TEST</groupId>
<artifactId>TEST</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.11.3</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.0</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release>18</release>
</configuration>
</plugin>
</plugins>
</build>
</project>
Solution
There is nothing wrong with Collections.addAll
.
I believe you expect all of your maps to be ListValuedMap<String, String>
which is basically a Map<String, List<String>>
. As such, your ListValuedMap<String, List<String>>
is a Map<String, List<List<String>>>
.
Just update each of your maps to be like below so each key is mapped to a List<String>
:
ListValuedMap<String, String> nonError = new ArrayListValuedHashMap<>();
ListValuedMap<String, String> numFormatError = new ArrayListValuedHashMap<>();
ListValuedMap<String, String> nullPointerError = new ArrayListValuedHashMap<>();
ListValuedMap<String, String> spreadTooHigh = new ArrayListValuedHashMap<>();
ListValuedMap<String, String> spreadNormal = new ArrayListValuedHashMap<>();
And then, instead of using ListValuedMap.put(K key, V value)
you have to use ListValuedMap.putAll(K key, Iterable<? extends V> values)
like this:
spreadNormal.putAll(stockName, stockMetadata);
spreadTooHigh.putAll(stockName, stockMetadata);
numFormatError.putAll(stockName, stockMetadata);
nullPointerError.putAll(stockName, stockMetadata);
The putAll
method will iterate over the stockMetadata
iterable and add the elements one by one into the map
‘s underlying list.
This Question was asked in StackOverflow by Dorian Feyerer and Answered by Dmitry Khamitov It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.