JAVA Arraylist unexpected output - java

Expected output :
Cell-1 Cell-2
Cell-3 Cell-4
But the output that I am getting is :
Cell-3 Cell-4
Cell-3 Cell-4
Why is this happening?
import java.util.ArrayList;
public class Test {
public static void main(String... a) {
String[][] var1 = new String[] []{{"Cell-1","Cell-2"},{"Cell-3","Cell-4"}};
ArrayList<String> r = new ArrayList<String>();
ArrayList<ArrayList<String>> var = new ArrayList<ArrayList<String>>();
//Insering data into the ArrayList.
for(String[] row : var1){
r.clear();
for(String data : row){
r.add(data);
}
var.add(r);
}
//Print data to console.
for(ArrayList<String> r1 : var){
for(String cell : r1)
System.out.print(cell+" ");
System.out.println();
}
}
}
`

This is not unexpected at all: you add the same object, namely ArrayList r, to the ArrayList var twice. First, you add it when it has Cell-1 Cell-2, then you clear it, and then you add it with Cell-3 Cell-4. The problem is, when you call r.clear(), the array list that you added to var gets cleared as well.
You need to create a new ArrayList instead of clearing the existing one to fix this problem: replace r.clear() with r = new ArrayList<String>(), and the problem will go away.

Related

Unique set from ArrayList of ArrayList

Hi I have an arraylist of arraylist in this format:
[[val1, val2],[val3,val4],[val1,val2],[val1,val5]]
and would like to get the unique set of arraylists:
[[val1, val2],[val3,val4],[val1,val5]]
I have tried the following:
Set<String> uniques = new HashSet<>();
for (ArrayList<String> sublist : mappedEntities) {
uniques.addAll(sublist);
}
but this merges all the values of the internal arraylist together
can use Java 8 Collection Stream Distinct,
return in Set datatype :
Set<List<String>> uniques = mappedEntities.stream().distinct().collect(Collectors.toSet());
if you want return in List :
List<List<String>> uniques = mappedEntities.stream().distinct().collect(Collectors.toList());
Why not simply put them in a Set like this?
Set<List<String>> uniques = new HashSet<>(mappedEntities);
Your mistake is that you are flattening the inner lists and putting their items in the set separately.
The issue here is that you need a Set of ArrayList Set<ArrayList<String>>, but you are using a Set of Strings Set<String> instead.
Given the list :
List<List<String>> mappedEntities = Arrays.asList(Arrays.asList("val1", "val2"),
Arrays.asList("val3", "val4"),
Arrays.asList("val1", "val2"),
Arrays.asList("val1", "val5"));
All you need to do is just declare the set and use the addAll().
Set<List<String>> mySet = new HashSet<>();
mySet.addAll(mappedEntities);
Since a set can hold only unique values, all duplicates will not be added to the set (No need to explicitly check this). You can now print it out :
mySet.forEach(System.out::println);
Or more simply, initialize the HashSet using the list mappedEntities :
Set<List<String>> mySet = new HashSet<>(mappedEntities);
I am beginner on STACKOVERFLOW but i to try solve your problem
I think you want like this..
import java.util.*;
public class GFG {
public static void main(String[] args)
{
int n = 3;
// Here aList is an ArrayList of ArrayLists
ArrayList<ArrayList<String> > aList =
new ArrayList<ArrayList<String> >(n);
// Create n lists one by one and append to the
// master list (ArrayList of ArrayList)
ArrayList<String> a1 = new ArrayList<String>();
a1.add("1");
a1.add("2");
aList.add(a1);
ArrayList<String> a2 = new ArrayList<String>();
a2.add("11");
a2.add("22");
aList.add(a2);
ArrayList<String> a3 = new ArrayList<String>();
a3.add("1");
a3.add("2");
aList.add(a3);
Set<ArrayList<String>> uniques = new HashSet<ArrayList<String>>();
for (ArrayList<String> sublist : aList) {
uniques.add(sublist);
}
System.out.println("Your Answer");
for (ArrayList<String> x : uniques)
System.out.println(x);
}
}
try this code:
public class B {
public static void main(String[] args) throws Exception {
List<List<String>> list= Arrays.asList(
Arrays.asList("a","b","c"),
Arrays.asList("a","b","c"),
Arrays.asList("a","b","c","d"));
Set<List<String>> uniques = new HashSet<>();
for (List<String> sublist : list) {
if(!uniques.contains(sublist))
uniques.add(sublist);
}
System.out.println(uniques);
}
}
output:
[[a, b, c], [a, b, c, d]]

Why do I need to create an array many times?

This programm shuffles a source list by pairs. So that original list
"1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20"
trasfoms to
11^12 19^20 17^18 15^16 1^2 5^6 3^4 13^14 7^8 9^10
The above is true while commented line is uncommented. Now, if line A is commented then all the elements in shuffleList are 19^20.
public class ShuffleService {
public static void shuffleList(List<String> list) {
System.out.println(list);
ArrayList<String[]> shuffleList = new ArrayList<String[]>(10);
String[] arr = new String[2];
boolean flag = false;
int step = 0;
for(String s: list){
if(flag){
arr[1]=s;
} else {
arr[0]=s;
}
flag=!flag;
step++;
if(step==2){
shuffleList.add(arr);
step=0;
//arr = new String[2]; //**line A**
}
}
Collections.shuffle(shuffleList);
for(String[] val: shuffleList){
System.out.print(val[0]);
System.out.print("^");
System.out.println(val[1]);
}
}
public static void main(String[] args) {
String[] a = new String[]{"1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20"};
List<String> list1 = Arrays.asList(a);
shuffleList(list1);
}
}
So why do I need to uncomment line A in the program to work properly?
Because when you rewrite the values to arr (without remaking it), you're also going to modify the values already in the list.
Adding an object to the list doesn't stop you from modifying it, it will not make copies on its own. By calling new String[2] in your loop you're effectively building a new string array for each pair that you add to the list, which is what you want.

Writing a method with ArrayList of strings as parameters

I am trying to write a method that takes an ArrayList of Strings as a parameter and that places a string of four asterisks in front of every string of length 4.
However, in my code, I am getting an error in the way I constructed my method.
Here is my mark length class
import java.util.ArrayList;
public class Marklength {
void marklength4(ArrayList <String> themarklength){
for(String n : themarklength){
if(n.length() ==4){
themarklength.add("****");
}
}
System.out.println(themarklength);
}
}
And the following is my main class:
import java.util.ArrayList;
public class MarklengthTestDrive {
public static void main(String[] args){
ArrayList <String> words = new ArrayList<String>();
words.add("Kane");
words.add("Cane");
words.add("Fame");
words.add("Dame");
words.add("Lame");
words.add("Same");
Marklength ish = new Marklength();
ish.marklength4(words);
}
}
Essentially in this case, it should run so it adds an arraylist with a string of "****" placed before every previous element of the array list because the lengths of the strings are all 4.
BTW
This consists of adding another element
I am not sure where I went wrong. Possibly in my for loop?
I got the following error:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at Marklength.marklength4(Marklength.java:7)
at MarklengthTestDrive.main(MarklengthTestDrive.java:18)
Thank you very much. Help is appreciated.
Let's think about this piece of code, and pretend like you don't get that exception:
import java.util.ArrayList;
public class Marklength {
void marklength4(ArrayList <String> themarklength){
for(String n : themarklength){
if(n.length() ==4){
themarklength.add("****");
}
}
System.out.println(themarklength);
}
}
Ok, so what happens if your list just contains item.
You hit the line if(n.length() ==4){, which is true because you are looking at item, so you go execute its block.
Next you hit the line themarklength.add("****");. Your list now has the element **** at the end of it.
The loop continues, and you get the next item in the list, which happens to be the one you just added, ****.
The next line you hit is if(n.length() ==4){. This is true, so you execute its block.
You go to the line themarklength.add("****");, and add **** to the end of the list.
Do we see a bad pattern here? Yes, yes we do.
The Java runtime environment also knows that this is bad, which is why it prevents something called Concurrent Modification. In your case, this means you cannot modify a list while you are iterating over it, which is what that for loop does.
My best guess as to what you are trying to do is something like this:
import java.util.ArrayList;
public class Marklength {
ArrayList<String> marklength4(ArrayList <String> themarklength){
ArrayList<String> markedStrings = new ArrayList<String>(themarklength.size());
for(String n : themarklength){
if(n.length() ==4){
markedStrings.add("****");
}
markedStrings.add(n);
}
System.out.println(themarklength);
return markedStrings;
}
}
And then:
import java.util.ArrayList;
public class MarklengthTestDrive {
public static void main(String[] args){
ArrayList <String> words = new ArrayList<String>();
words.add("Kane");
words.add("Cane");
words.add("Fame");
words.add("Dame");
words.add("Lame");
words.add("Same");
Marklength ish = new Marklength();
words = ish.marklength4(words);
}
}
This...
if(n.length() ==4){
themarklength.add("****");
}
Is simply trying to add "****" to the end of the list. This fails because the Iterator used by the for-each loop won't allow changes to occur to the underlying List while it's been iterated.
You could create a copy of the List first...
List<String> values = new ArrayList<String>(themarklength);
Or convert it to an array of String
String[] values = themarklength.toArray(new String[themarklength.size()]);
And uses these as you iteration points...
for (String value : values) {
Next, you need to be able to insert a new element into the ArrayList at a specific point. To do this, you will need to know the original index of the value you are working with...
if (value.length() == 4) {
int index = themarklength.indexOf(value);
And then add a new value at the required location...
themarklength.add(index, "****");
This will add the "****" at the index point, pushing all the other entries down
Updated
As has, correctly, been pointed out to me, the use of themarklength.indexOf(value) won't take into account the use case where the themarklength list contains two elements of the same value, which would return the wrong index.
I also wasn't focusing on performance as a major requirement for the providing a possible solution.
Updated...
As pointed out by JohnGarnder and AnthonyAccioly, you could use for-loop instead of a for-each which would allow you to dispense with the themarklength.indexOf(value)
This will remove the risk of duplicate values messing up the index location and improve the overall performance, as you don't need to create a second iterator...
// This assumes you're using the ArrayList as the copy...
for (int index = 0; index < themarklength.size(); index++) {
String value = themarklength.get(index);
if (value.length() == 4) {
themarklength.add(index, "****");
index++;
But which you use is up to you...
The problem is that in your method, you didn't modify each string in the arraylist, but only adds 4 stars to the list. So the correct way to do this is, you need to modify each element of the arraylist and replace the old string with the new one:
void marklength4(ArrayList<String> themarklength){
int index = 0;
for(String n : themarklength){
if(n.length() ==4){
n = "****" + n;
}
themarklength.set(index++, n);
}
System.out.println(themarklength);
}
If this is not what you want but you want to add a new string "**" before each element in the arraylist, then you can use listIterator method in the ArrayList to add new additional element before EACH string if the length is 4.
ListIterator<String> it = themarklength.listIterator();
while(it.hasNext()) {
String name = it.next();
if(name.length() == 4) {
it.previous();
it.add("****");
it.next();
}
}
The difference is: ListIterator allows you to modify the list when iterating through it and also allows you to go backward in the list.
I would use a ListIterator instead of a for each, listiterator.add likely do exactly what you want.
public void marklength4(List<String> themarklength){
final ListIterator<String> lit =
themarklength.listIterator(themarklength.size());
boolean shouldInsert = false;
while(lit.hasPrevious()) {
if (shouldInsert) {
lit.add("****");
lit.previous();
shouldInsert = false;
}
final String n = lit.previous();
shouldInsert = (n.length() == 4);
}
if (shouldInsert) {
lit.add("****");
}
}
Working example
Oh I remember this lovely error from the good old days. The problem is that your ArrayList isn't completely populated by the time the array element is to be accessed. Think of it, you create the object and then immediately start looping it. The object hence, has to populate itself with the values as the loop is going to be running.
The simple way to solve this is to pre-populate your ArrayList.
public class MarklengthTestDrive {
public static void main(String[] args){
ArrayList <String> words = new ArrayList<String>() {{
words.add("Kane");
words.add("Cane");
words.add("Fame");
words.add("Dame");
words.add("Lame");
words.add("Same");
}};
}
}
Do tell me if that fixes it. You can also use a static initializer.
make temporary arraylist, modify this list and copy its content at the end to the original list
import java.util.ArrayList;
public class MarkLength {
void marklength4(ArrayList <String> themarklength){
ArrayList<String> temp = new ArrayList<String>();
for(String n : themarklength){
if(n.length() ==4){
temp.add(n);
temp.add("****");
}
}
themarklength.clear();
themarklength.addAll(temp);
System.out.println(themarklength);
}
}

Insertion Sort using an array list java

I have no idea how to get my new list to print
import java.util.ArrayList;
import java.util.List;
public class InsertionSort {
public static int insertion(List<String> sorted) {
sorted = new ArrayList<String>();
String list[] = {"Banana","Pear","Apple","Peach","Orange"};
String temp="";
int f = list.length;
for(int i=0;i<f;i++){
for(int j=i+1;j<f;j++){
if(list[i].compareToIgnoreCase(list[j])>0){
temp = list[i];
list[i]=list[j];
list[j]=temp;
}
}
}
System.out.print(list);
return list[].InsertionSort;
I keep getting this error for the line above
1 error found:
InsertionSort.java [line: 22]
Error: class expected
}
}
You want to use the for-each loop, it will look like so :
for ( String i : list){
System.out.print(i);
}
You can't print out the array like you did here:
System.out.print(list); // DOES NOT WORK
Because println takes in a variety of parameters, but not an array( although one version takes an array of chars ). See the API
But if you said,...
System.out.print(list[1]);
for example, it would compile..
You have other issues to fix though..
return list[].InsertionSort //what's mean is code?
if you want to print list you can like this:
for(String str:list) //this list is list<String>
{
System.out.println(str);
}

Java:HashMap<String,String> storing same value as key and value.?

I am getting this strange output in HashMap.
I have two ArrayList<String> one containing the key and another containing value.
My HashMap<String,String> will store only string as key and value pair. But key itself is getting stored in value. I have checked my value arraylist, it's printing the value. But during putting it's setting it as key itself.
Code snippet is:
public HashMap<String,String> getLstBarring()
{
ArrayList<String> temparrLst=setPreParameters(fetchPreDetails, 1);
System.out.println("KEY" + temparrLst);
ArrayList<String> tempArrLstId=setPreParameters(fetchPreDetails, 14);
System.out.println("VALUE" +tempArrLstId);
int length=tempArrLstId.size();
for(int index=0;index<length;index++)
{
System.out.println("VALUE IN KEY" + temparrLst.get(index));
System.out.println("VALUE IN VALUE" + tempArrLstId.get(index));
this.lstBarring.put(temparrLst.get(index), tempArrLstId.get(index));
}
System.out.println("INSIDE ODB....>>>>>>>>>>>>>>" + lstBarring);
return this.lstBarring;
}
Problem is:
1st SOP is KEY-printing all the key correctly.
2nd SOP is VALUE-printing all the value correctly.
3rd SOP is VALUE IN KEY----printing all the values.
4th SOP is VALUE IN VALUE--printing all the values.
Hence after ever iteration I am getting value,value in HashMap whereas it should be key,value.
Here's look at my Method:-
public ArrayList<String> setPreParameters(HashMap<Integer,String> fetchPreDetails,int index)
{
switch(index)
{
case 1:
{
arrLstData.clear();
splittedString=fetchPreDetails.get(1).split(",");
Collections.addAll(arrLstData, splittedString);
break;
}
return arrLstData;
Please guide me as to where am I going wrong.
My guess is that either fetchPreDetails is a collection being mutated by setPreParameters() or else setPreParameters() is mutating some other shared state so that the collection referenced by your temparrLst is being changed on the second call to setPreParameters(). I.e.
List<String> strings = new ArrayList();
strings.add("a");
strings.add("b");
List<String> otherStrings = strings;
otherStrings.add("c");
I expect your code assumes that strings would contain "a" and "b" and that otherStrings would contain "a", "b", and "c". This isn't how object references work in Java. The line List<String> otherStrings = strings; makes both strings and otherStrings point to the same collection, and thus changes made using either name affect the same thing.
Edit: Your newly-posted code seems to prove my hypothesis. You have a variable called arrLstData that you clear, populate, and return on each call to setPreParameters(). You're returning the same collection every time you call this method. Therefore you just have multiple handles to the same collection instead of multiple collections. You need to create a new collection and return it each time you call setPreParameters().
Edit again: Maybe this will make it clearer. Here's what you're doing:
public static void main(String[] args) {
Foo f = new Foo();
List<String> list1 = f.getList("a", "b");
System.out.println(list1);
List<String> list2 = f.getList("c", "d");
System.out.println(list2);
System.out.println(list1);
}
static class Foo {
private List<String> myList = new ArrayList<String>();
public List<String> getList(String... strings) {
myList.clear();
myList.addAll(Arrays.asList(strings));
return myList;
}
}
Note that this exhibits exactly the behavior that you're describing, and the correct way to solve it is something like this:
public static void main(String[] args) {
Foo f = new Foo();
List<String> list1 = f.getList("a", "b");
System.out.println(list1);
List<String> list2 = f.getList("c", "d");
System.out.println(list2);
System.out.println(list1);
}
static class Foo {
public List<String> getList(String... strings) {
List<String> result = new ArrayList<String>();
result.addAll(Arrays.asList(strings));
return result;
}
}
You are reusing the same List over and over at your setPreParameters Method.
The List in arrLstData is returned and stored in temparrLst, now you are clearing the the Lists content, putting new stuff in it and storing it to tempArrLstId.
Now the three variables all contain the very same list (they are not equals, its the same!).
There is only one List object at the whole example!
Its like you got a box and label it "A" on one side put stuff in it, label it "B" on another side and wondering why the box "B" is empty when you turn box "A" upside-down.
Did you maybe mean something like this?
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class GlobalsMess {
private Map<String, String> lstBarring = new HashMap<String, String>();
private Map<Integer, String> fetchPreDetails = new HashMap<Integer, String>();
public GlobalsMess() {
fetchPreDetails.put(1, "john,vikam,david");
fetchPreDetails.put(14, "1,2,3");
}
public Map<String, String> getLstBarring() {
List<String> tempKeys = setPreParameters(fetchPreDetails.get(1));
System.out.println("KEY" + tempKeys);
List<String> tempIds = setPreParameters(fetchPreDetails.get(14));
System.out.println("VALUE" + tempIds);
for (int index = 0; index < tempIds.size(); index++) {
System.out.println("VALUE IN KEY" + tempKeys.get(index));
System.out.println("VALUE IN VALUE" + tempIds.get(index));
this.lstBarring.put(tempKeys.get(index), tempIds.get(index));
}
System.out.println("INSIDE ODB....>>>>>>>>>>>>>>" + lstBarring);
return this.lstBarring;
}
public List<String> setPreParameters(String fetchPreDetailsValue) {
List<String> arrLstData = new ArrayList<String>();
Collections.addAll(arrLstData, fetchPreDetailsValue.split(","));
return arrLstData;
}
public static void main(String[] args) {
new GlobalsMess().getLstBarring();
}
}
Output:
KEY[john, vikam, david]
VALUE[1, 2, 3]
VALUE IN KEYjohn
VALUE IN VALUE1
VALUE IN KEYvikam
VALUE IN VALUE2
VALUE IN KEYdavid
VALUE IN VALUE3
INSIDE ODB....>>>>>>>>>>>>>>{david=3, vikam=2, john=1}

Categories

Resources