How can I add an ArrayList to a hash map (as values) and clear said ArrayList afterwards (Java) - arraylist

I want to add an ArrayList of values to a hashmap, and then clear the ArrayList, so that I may use the same ArrayList for other values on different keys of the hashmap.
My attempts led me to either the ArrayList getting a single value, all values from the input I was receiving, or no values at all.

Map<String,List<Integer>> map = new HashMap<>();
List<Integer> list = new ArrayList<>();
list.addAll(Arrays.asList(1,2,3));
map.put("first", List.copyOf(list));
list.clear();
list.addAll(Arrays.asList(7,8,9));
map.put("second", List.copyOf(list));

Related

java8 make immutable List after removing null elements

I know Arrays.asList creates immutable List. My requirement is to create immutable List<Student> with no null elements in it. So I am creating new ArrayList() first then removing null elements using java 8 filters as shown below:
List<Student> list = new ArrayList<>();
list.add(makeStudent("ram", 'M'));
list.add(makeStudent("sathya", 'F'));
list.add(makeStudent(null, 'M'));
list.add(makeStudent("sri", 'M'));
list = list.stream().filter(s -> s != null).collect(Collectors.toList());
Below is the makeStudent method, it returns null if name is not available:
private Student makeStudent(String name, char gender) {
return null != name ? new Student(name, gender) : null;
}
I thought Collectors.toList() will create immutable. But I was wrong. The list is still mutable here. Is there a better way to make the list clean (remove null) and immutable in single line using java 8?
You might rewrite your code to this one:
list = list.stream()
.filter(Objects::nonNull)
.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
Collector collectingAndThen allow you to wrap result collection
Even though you specified Java 8, here is how you can filter an existing List into a fully immutable List that you're looking for with Java 9:
list = list.stream()
.filter(Objects::nonNull)
.collect(Collectors.toCollection(List::of));
using Collections.unmodifiableList to wrap the List collected by the stream.
list = Collections.unmodifiableList(list.stream()
.filter(Objects::nonNull)
.collect(Collectors.toList()));
the Collectors.toList() method do the things like as reduce:
//pseudo-code
Collectors.reduce(ArrayList::new, List::add, List::addAll)
IF you passing an immutable List to reduce you can't collect any items from the stream into the List since it is immutable.
You can either use Collections.unmodifiableList as suggested in other answers or you can also convert stream to array and then use Arrays.asList.
list = Arrays.asList(list.stream()
.filter(Objects::nonNull)
.toArray(Student[]::new));

Verify HTML Table using Selenium

Can someone let me know which approach is good for verifying HTML Table. I have to write test case related to adding/deleting/editing HTML table using selenium.
Table looks like this
Name and Branch could be duplicate, the only way to uniquely Identify the row is using id (First column).
I am using the page object pattern, so I need to write the function for adding/editing/deleting and verifying that row exist or not.
how should I write a function to add record and then a separate function to verify that record has been added successfully. As the name could be duplicate I can not verify if name exist in the table or not. The other way is, I return the ID of last row once I add the record. And then I can verify if name on last id is same as I recently added. However this approach has some glitch as well.
is there any better approach for this situation.
For add test case, you could create a function in your PageObject that returns the count of rows that have the same value in the Name field.
In your test case,
Store this number in a variable
Add a record
Back to the grid screen, invoke the row counting function again, comparing it with the stored value
It must be the stored value + 1, otherwise something is wrong.
As an additional check, you could also store the total number of rows in the table prior adding, and check if that value has also increased by one after edition (ensuring no record has been replaced in the process).
Note: If you're using PageFactory, you could also create an IList with the rows in the table, and use its count property instead of creating a counting function.
Edit:Your add method can be stored inside your PageObject, so that you have it separated from assertion. Even if you return the id, without knowing what was in the table prior adding your record, a separated individual verification won't be of much use.
So without seeing the html for this table, I'll have to make some assumptions. It looks like the ID column are hyperlinks, so the xpath for those will be slightly different from the other cells. Okay, so onto the solution.
We first need to think about how we're going to store the data from the table. You want some kind of 2 dimensional object that is easy to work with. I like to use HashMap to store the individual rows. HashMap stores information in un-ordered, key-value pairs. They Key would be the name of the column, and the Value would be the value of that cell for that row.
To store a table's worth of data, I would then put each of those rows that are stored in separate HashMaps and put that into an ArrayList.
Now onto how to scrape the data, the fastest solution is always the one that does the least number of lookups and calls to Selenium. In this case since you have all kinds of weirdness going on with the table, I would target all of the data cells with one lookup.
Without seeing the HTML, my xpath would look something like //table[#id='something']/tbody/tr/td[1]/a|//table[#id='something']/tbody/tr/td[not(./a[./text()='View' or ./text()='Edit' or ./text()='Delete'])]
The Pipe symbol conjoins the 2 xpaths together so it will target both types of cells in the correct order.
Here's my generic TableData class. You create an instance of this class to store the data. The data itself gets stored in the _data object.
public class TableData {
public ArrayList<HashMap<String, String>> _data;
public TableData(ArrayList<HashMap<String, String>> data) {
_data = data;
}
public static TableData get_SiteTable_ByCell(WebDriver driver, By tableCells, String[] headerValues) {
ArrayList<WebElement> tableCellElements = new ArrayList<WebElement>(driver.findElements(tableCells));
ArrayList<HashMap<String, String>> data = new ArrayList<HashMap<String, String>>();
int numberRows = tableCellElements.size() / headerValues.length;
for (int i = 0; i < numberRows; ) {
HashMap<String, String> newRow = new HashMap<>();
for (int j = 0; j < headerValues.length; j++, i++) {
newRow.put(headerValues[j], tableCellElements.get(i).getText());
}
data.add(newRow);
}
return new TableData(data);
}
}
So now that we have our method for getting the data, the values that I need to pass in are...
public TableData getTable(WebDriver driver)
{
String[] headers = {"ID", "Name", "Branch"};
By cellsBy = By.xpath("//table[#id='something']/tbody/tr/td[1]/a|//table[#id='something']/tbody/tr/td[not(./a[./text()='View' or ./text()='Edit' or ./text()='Delete'])]");
return TableData.get_SiteTable_ByCell(driver, cellsBy, headers);
}
Okay, so now we want to get a specific row. I need to write a method that will return a HashMap for the given criteria. This will also go in the TableData class from earlier.
public HashMap<String, String> returnRow(String columnName, String columnValue){
for(HashMap<String, String> row : _data){
if(row.get(columnName).equals(columnValue)){
return row;
}
}
return null;
}
So now that I have all that, my code would look something like...
#Test
public void newTest1()
{
TableData customerTable = getTable(driver);
HashMap<String, String> rowWeWant = customerTable.returnRow("ID", "1");
String valueWeWant = rowWeWant.get("Name");
}

Map implementaion using arraylist as value

I am using Maps in my code for the first time, hence require some inputs from you experts.
My requirement is I have to check two different tables from database. Value from First table will be used as Key and Value for second table will be used as Value for the key.
Each key will have multiple values, so I will be storing all values against each key in a arraylist i.e. my Map will be like MAP.
Now, my issue is following:
I don't know the total no. of keys, so I can't create arraylist objects in advance. How to manage this?
How can I check if key exists in map such that if it exists then I have to updated the arraylist corresponding to it only. And if it doesn't exist then create new key, create arraylist corresponding to it, populate arraylist with the value.
Finally I have to iterate whole map and use the key and values.
How can it be implemented? Am I following the right approach? if not what is a better approach?
Thanks
With lists in Java you do not need to know the size up front. That is a requirement for Arrays. Therefore just create your Map
Map> myMap = new HashMap<>();
This should work
if (myMap.containsKey(someKey)) {
myMap.get(someKey).add(someValue); // adds a value to the list that already is in the map
} else {
myMap.put(someKey, Arrays.asList(someValue)); // which inserts a new key/value
}
If you need to iterate over all values in the list then you need a nested for loop
for (Map.Entry> entry : myMap.entrySet()) {
// your key = entry.getKey()
for (ValueType value : entry.getValue()) {
// use your value
}
}
http://docs.oracle.com/javase/7/docs/api/java/util/Map.html
Hope that helps.

How to search by key in hashset?

I wanted a collection that would contain a bunch of unique strings. Hashset seemed to be the best option since it removes duplicates and is quick about it.
However how would i go about finding an item in the hash set? I could just loop through all the elements but wouldn't that defeat the purpose of being a hashset? Essentially i just want a dictionary where the key is the value.
Hashsets are not used for searching. They are used to treat collection as a whole. You can use it as for what mathematical sets are used for: to create unions, intersections, or for checks of duplication etc.
The dictionaries and hashsets are similar in internal implementation, since they are based on hashtables. But sets do not have keys, since they are not allowed for the lookup of the elements. You must use dictionary for it. If you want to ask a set for an element, you will have to enumerate thru them all.
In the same way, you should not use Queues, stacks or linked list for looking for an element.
To have only strings in a dictionary you can use it like:
IDictionary<string, string dictionary =
new Dictionary<string, string>();
dictionary.Add("Foo", "Foo");
dictionary.Add("Bar", "Bar");
string stringThatILookFor = null;
if (dictionary.TryGetValue("Bar", out stringThatILookFor))
{
// Use stringThatILookFor, which has a value Bar
}
You need to be using Contains.
Dim hsStrings As HashSet(Of String) = {"a", "b", "c"}
If hsStrings.Contains("a") Then 'do smth

arraylist checks

I have an arraylist that contains urls in the form similar to :
stackoverflow.com/questions/ask/hello
stackoverflow.com/questions/ask
stackoverflow.com/questions
stackoverflow.com/
If I only wanted to keep the first one and remove the rest, how would I go about doing that since technically they are not duplicates.
I thought of using substring manipulation but not to sure how to implement that.any ideas appreciated.
Assuming I understand the question correctly, you can accomplish this by looping through your ArrayList, building a list of found domains, and simultaneously outputting a new list only when the found domain is not already a member of that first list.
Or, you could build a dictionary of domain to url by iterating through the ArrayList in reverse. Since a dictionary can only have one value per key, the URLs will overwrite themselves in the dictionary and you will only have one URL per domain. Since you iterated in reverse, you will be left with a dictionary containing the first match in the ArrayList. You could then use LINQ to grab just the values (e.g. MyDictionary.Select(elem => elem.Value)).
An example implementation of the second way I mentioned (in C#, you can convert it) is:
Dictionary<string, string> MyDictionary = new Dictionary<string, string>();
foreach(string Url in MyArrayList.Reverse())
MyDictionary[Url.Split("/")[0]] = Url;
There are dozens of ways you could accomplish this task. These are just two examples.