Java convert Set<Set<String>> to List<List<String>> - java

In Java I am having trouble converting from a Set<Set<String>> to a List<List<String>> and then populating this list with the contents of the Set<Set<String>>
Here is my code:
Set<Set<String>> treeComps = compExtractor.transform(forest); // fine
List<List<String>> components = new List<List<String>>(); // does not work
components.addAll(treeComps); // does not work

You can't instantiate an instance of the List interface, you need to use one of the implementations like ArrayList. Then you can iterate over the outer set in treeComps, create a new ArrayList for each inner set, call addAll on this ArrayList and then add the list to components.
List<List<String>> components = new ArrayList<List<String>>();
for( Set<String> s : treeComps )
{
List<String> inner = new ArrayList<String>();
inner.addAll( s );
components.add( inner );
}

I think only way is iterate over outer set. Get inner set and user new ArrayList<String>(innerSet)
Add above result list to outerlist.

Something like this...
Set<Set<String>> treeComps = compExtractor.transform(forest);
List<List<String>> lists = new ArrayList<List<String>>();
for (Set<String> singleSet : treeComps) {
List<String> singleList = new ArrayList<String>();
singleList.addAll(singleSet);
lists.add(singleList);
}

List<List<String>> components = new Vector<List<String>>();
List<String> n;
for( Set<String> s : trerComps ) {
n = new Vector<String>();
n.addAll( s );
components.add( n);
}

Related

I want to write a function that checks a 2-d List for duplicate elements

I want to write a function that checks a 2-d List for duplicate elements. For example: [[key1, key2], [key1, key3]] "key1" is duplicate. I want to remove or replace it e.g with n\a. What I have tried so far.
private static List<List<String>> removeRedundantStrings(List<List<String>> list) {
List<List<String>> outList = new ArrayList<>();
List<String> oneDimension = new ArrayList<>();
for (var tempList : list) {
for (var string : tempList) {
if (!oneDimension.contains(string))
oneDimension.add(string);
else
oneDimension.add("n/a");
outList.add(oneDimension);
}
}
return outList;
}
This "solution" results in: [[key1, key2, n/a, key3]] - not a "true" 2-d list. How would I achieve the same format as the input list? The result would be: [[key1, key2], [n/a, key3]]. Am I missing something else?
You should create the inner List in the correct place - inside the outer loop.
In addition, I'd use a single HashSet to keep track of the Strings that already appeared.
List<List<String>> outList = new ArrayList<>();
Set<String> uniques = new HashSet<>();
for (var tempList : list) {
List<String> oneDimension = new ArrayList<>();
for (var string : tempList) {
if (uniques.add(string)) // add will return true if string was actually added to Set
oneDimension.add(string);
else
oneDimension.add("n/a");
}
}
outList.add(oneDimension);
}

How to edit the Hashmap list values based on the Key

I need to edit the list values based on the key .
My code is:
HashMap<String,List<String>> map= new HashMap<String,List<String>>()
List<String> listOMSColorCode = new ArrayList<String>()
List<String> listOMSColorCodeDisplayOrder = new ArrayList<String>()
listOMSColorCode.add("orange")
listOMSColorCode.add("apple")
listOMSColorCode.add("banana")
map.put("Key1",listOMSColorCode)
after some logic happen here , Now I want to replace/edit apple with grapes in the same index of map list.
You could use a ListIterator for that:
for(ListIterator<String> li = listOMSColorCode.listIterator(); li.hasNext(); ) {
if(li.next().equals("apple")) {
li.set("grape");
}
}
if(li.next().equals("apple")) { checks if the current element of the listIterator is an "apple" and if it is. It replaces that element with "grape" via the the ListIterator.set() method
Not very efficient, because it iterates the list for every occurence, but this will replace all occurences:
List<String> modifiedList = map.get("Key1");
int index = 0;
while((index = modifiedList.indexOf("apple")) != -1){
modifiedList.set(index, "grapes");
}
Or using a utility method from Collections class:
List<String> modifiedList = map.get("Key1");
Collections.replaceAll(modifiedList, "apple", "grapes");

How to store all ArrayList<ArrayList<String>> values into ArrayList<String>?

I am having issue to store all values of ArrayList<ArrayList<String>> into ArrayList<String>. Here stylistIDArray and durationArray are array of array. I want to store all their values in stylistId and duration respectively. The stylistid and duration are array of string.
Here's my attempt, but it stores only the last item of each array of array.
ArrayList<ArrayList<String>> stylistIDArray;
ArrayList<ArrayList<String>> durationArray;
stylistIDArray = differentGenderServicesAdapter.getSelectedStylistIdArray();
durationArray = differentGenderServicesAdapter.getSelectedDurArray();
ArrayList<String>stylistId = new ArrayList<>();
ArrayList<String>duration = new ArrayList<>();
for(int i=0; i<stylistIDArray.size(); i++) {
stylistId = stylistIDArray.get(i);
duration = durationArray.get(i);
}
Note : I have already tried this, but doesn't work for me.
To be generic, First let be an list of list of objects
List<List<Object>> listOfList;
That you want to put into a list of object
List<Object> result;
Note the result list will contain every object contain is the input list. This transformation will loose the information of which object was in which list.
You have to loop through the listOfList. At each loop you obtain a list of object (List<Object> listOfObject). Then loop through these lists to obtain every object (Object o). Then add these object to the result list (result.add(o)).
for(List<Object> listOfObject : listOfList) {
for(Object o : listOfObject) {
result.add(o);
}
}
In your case, the problem is that you use affectation instead of add(). At every loop this replaces the value by the new one. So at the end you have stored only the last item of each list.
stylistId=stylistIDArray.get(i); //This replace the existing stylistId
Instead try something like
ArrayList<ArrayList<String>> stylistIDArray;
ArrayList<ArrayList<String>> durationArray;
stylistIDArray = differentGenderServicesAdapter.getSelectedStylistIdArray();
durationArray = differentGenderServicesAdapter.getSelectedDurArray();
ArrayList<String> stylistId = new ArrayList<>();
ArrayList<String> duration = new ArrayList<>();
for(ArrayList<String> l : stylistIDArray) {
for(String s : l) {
stylistId.add(s);
}
}
for(ArrayList<String> l : durationArray ) {
for(String s : l) {
duration.add(s);
}
}
You doing wrong operation with arraylist, in loop you are getting data from stylistIDArray and assign to aryalist, not inserting in list, have look this
stylistIDArray=differentGenderServicesAdapter.getSelectedStylistIdArray();
durationArray=differentGenderServicesAdapter.getSelectedDurArray();
ArrayList<String>stylistId=new ArrayList<>();
ArrayList<String>duration=new ArrayList<>();
for(int i=0; i<stylistIDArray.size(); i++) {
stylistId.add(stylistIDArray.get(i));
duration.add(durationArray.get(i));
}
Hope it will help you!

Create a Set of lists from two lists through recursion

I've searched through many questions on this site with somewhat similar underlying concepts, however after many hours of attempting to solve this problem myself and reviewing I am still lost. If there is another question that answers this I will be more than happy to give it a look over.
Ultimately I want to create a recursive method such that it takes two lists and returns a Set of String lists:
//Example of such a function definition
private static Set<List<String>> myRecursiveMethod(List<String> listOne,
List<String> listTwo) {
}
When I say "Set of String lists" I mean specifically the following:
(Note:"AD" == "DA")
// if the two following lists are INPUTTED into myRecursiveMethod();
// listOne = ["A","B"]
// listTwo = ["C","D"]
// the following set is OUTPUTTED: [["AC","BD"],["AD","BC"]]
Such that if there were three elements in both listOne and listTwo, there would be SIX elements in the set. i.e:
// listOne = ["A","B","C"]
// listTwo = ["D","E","F"]
// OUTPUTTED: [["AD","BE","CF"],["AD","BF","CE"],["BD","AE","CF"],
// ["BD","AF","CE"],["CD","AE","BF"],["CD","AF","BE"]]
I tried writing this using a double enhanced FOR loop so I could understand the logic. My FOR loop approach is terrible and only works for the HARD-CODED limit of list.size() == 2.
// Create Lists and append elements
List<String> listOne = new ArrayList<String>();
listOne.add("A");
listOne.add("B");
List<String> listTwo = new ArrayList<String>();
listTwo.add("C");
listTwo.add("D");
// List One = ["A","B"]
// List Two = ["C","D"]
// Create new List
List<List<String>> newList = new ArrayList<List<String>>();
Integer counter = 0;
for (String s : listOne) {
counter++;
for (String p : listTwo) {
// A HARD-CODED bad implementation of this method
if (counter < 3) {
List<String> newListTwo = new ArrayList<String>();
newListTwo.add(s.concat(p));
newList.add(newListTwo);
} else if (!(counter % 2 == 0)) {
newList.get(1).add(s.concat(p));
} else {
newList.get(0).add(s.concat(p));
}
}
}
System.out.println(newList); // = [["AC","BD"],["AD","BC"]]
Also you can note that I defined List<List<String>> Rather than Set<List<String>>. This was due to my badly coded attempted which relies on the list.get() method.
So my current recursive method is as follows:
private static Set<List<String>> myRecursiveMethod(List<String> listOne,
List<String> listTwo)
{
//Base Case:
if (listOne.isEmpty){
return new HashSet<List<String>>;
}
//Recursive Case:
else {
String listOneFirst = listOne.get(0);
String listTwoFirst = listTwo.get(0);
List<String> sampleList = new ArrayList<String>();
sampleList.add(listOneFirst+listTwoFirst);
Set<List<String>> newSet = new HashSet<List<String>>(myRecursiveMethod())
newSet.add(sampleList);
return newSet;
}
}
This method only acts like this currently:
INPUT:
List One = ["A","B"]
List Two = ["C","D"]
OUTPUT:
[["AC"]["BD"]]
DESIRED OUTPUT:
[["AC","BD"],["AD","BC"]]
EDIT:
After reviewing responses my W.I.P code for the class:
private static Set<List<String>> myRecursiveMethod(List<String> listOne,
List<String> listTwo) {
//Backup Case (user enters an empty list)
if (listOne.isEmpty()){
return new HashSet<List<String>>();
}
// Base Case:
if (listOne.size() == 1) {
List<String> mergedStrings = new ArrayList<>();
for (String s : listTwo) {
mergedStrings.add(listOne.get(0).concat(s));
}
Set<List<String>> builtHashSet = new HashSet<List<String>();
builtHashSet.add(mergedStrings);
return builtHashSet;
}
// Recursive Case:
else {
// Ensure original list values arn't changed.
List<String> newListOne = new ArrayList<String>(listOne);
List<String> newListTwo = new ArrayList<String>(listTwo);
//first two elements...I don't think this is correct
String listOneFirst = newListOne.get(0);
String listTwoFirst = newListTwo.get(0);
List<String> sampleList = new ArrayList<String>();
sampleList.add(listOneFirst + listTwoFirst);
//used for making recursive case smaller
newListOne.remove(0);
// Calls recursion
Set<List<String>> newSet = new HashSet<List<String>>(
myRecursiveMethod(newListOne, newListTwo));
newSet.add(sampleList);
return newSet;
}
}
I think the problem is here:
if (listOne.isEmpty){
return new HashSet<List<String>>;
}
You are correct, at some point your recursion has to end, and you have to start building the desired output. But the desired output is not a Set with an empty list. It is a Set containing some lists with some content. Thus: don't wait until listOne is empty. Instead:
if (listOne.size() == 1) {
List<String> mergedStrings = new ArrayList<>();
mergedStrings = ... merge the ONE listOne entry with all listTwo entries
Set<List<String>> rv = new HashSet<>();
rv.add(mergedStrings);
return rv;
}
In other words: you use recursion to reduce the length of the first list by one. And when only one element is left in that list, it is time to merge in the second list.
Now lets look into how to "use" that (calling the method rec for brevity); putting down some pseudo code to show the steps we need:
rec([a, b], [c,d]) -->
rec([a], [c,d]) X rec([b], [c, d]) -->
<[ac, ad]> X <[bc, bd]> -->
<[ac, ad], [bc, bd]>
"X" meaning "joining" two results from recursive calls; should be as easy as:
Set<List<String>> rec1 = rec(...);
return rec1.addAll(rec2 ...

How to assert ArrayList of String ArrayList equal in TestNG

I have a method that groups a given String ArrayList into ArrayList of String ArrayList, with each of the String ArrayList containing strings of the same length. The method is:
public static ArrayList> getGrouping(ArrayList strlist)
{
Map<Integer, ArrayList<String>> mapOfList = new HashMap<Integer, ArrayList<String>>();
/*
* Define ArrayList of ArrayList to build the output to return, and,
*another ArrayList to act as sub-array to build the output
*/
ArrayList<ArrayList<String>> outer = new ArrayList<ArrayList<String>>();
ArrayList<String> inner = new ArrayList<String>();
String temp;
/*
* populate the map of lists in the format map <length of string , list of strings of this length
*/
for(int i = 0; i <strlist.size(); i++)
{
temp = strlist.get(i);
if (temp == null)
continue;
int len = temp.length();
len = new Integer(len);
if(mapOfList.get(len) == null)
{
mapOfList.put(len, new ArrayList<String>());
}
mapOfList.get(len).add(temp);
}
/*
* Build sub ArrayList using ArrayList at every entry and add this to the outer ArrayList to be returned
*/
for(Map.Entry<Integer, ArrayList<String>> entry : mapOfList.entrySet())
{
inner = entry.getValue();
outer.add(inner);
}
return outer;
}
I am new to TestNG and trying to write test methods for the above. I am having trouble building the expected result (which is ArrayList of String ArrayList). What's the best way to do it? The way I do it now throws the error:
java.lang.ClassCastException: java.util.Arrays$ArrayList cannot be cast to java.util.ArrayList
Also they way I build the input is probably not the best way. Could this be done better? The TestNG #Test method I have now which fails is:
public void testWithNullValues()
{
ArrayList<ArrayList<String>> oup = new ArrayList<ArrayList<String>>();
ArrayList<String> inp = new ArrayList<String>();
inp.add("abc");
inp.add("ba");
inp.add("bdc");
inp.add(null);
inp.add("bfed");
inp.add(null);
inp.add("bdsf");
inp.add("a");
inp.add("b");
inp.add("bdcjkhwd");
oup = GroupListOfString.getGrouping(inp);
ArrayList<ArrayList<String>> expectedResult = new ArrayList<ArrayList<String>>();
expectedResult.add((ArrayList<String>) Arrays.asList("a", "b"));
expectedResult.add((ArrayList<String>) Arrays.asList("ba"));
expectedResult.add((ArrayList<String>) Arrays.asList("abc", "bdc"));
expectedResult.add((ArrayList<String>) Arrays.asList("bfed","bdsf"));
expectedResult.add((ArrayList<String>) Arrays.asList("bdcjkhwd"));
Assert.assertEquals(expectedResult, oup);
inp.clear();
}
Thanks in Advance!
Arrays.asList returns a java.util.Arrays.ArrayList, which is not the same as a java.util.ArrayList the rest of your class uses. You could, however, just construct one:
ArrayList<ArrayList<String>> expectedResult = new ArrayList<>();
expectedResult.add(new ArrayList<>(Arrays.asList("a", "b")));
expectedResult.add(new ArrayList<>(Arrays.asList("ba")));
expectedResult.add(new ArrayList<>(Arrays.asList("abc", "bdc")));
expectedResult.add(new ArrayList<>(Arrays.asList("bfed","bdsf")));
expectedResult.add(new ArrayList<>(Arrays.asList("bdcjkhwd")));
Assert.assertEquals(expectedResult, oup);

Categories