arraylist loading gives me interesting output - java

i have this simple method:
public static Map<String, ArrayList<String>> szamolando = new HashMap<String,ArrayList<String>>();
ArrayList<String> outputs = new ArrayList<String>();
for(int i = 0;i<2;i++){
tombFeltolt("a"+i);
}
public void tombFeltolt(String kimenet) {
outputs.clear();
System.out.println("1");
outputs.add(min);
System.out.println("2");
outputs.add(max);
System.out.println("3");
outputs.add("65535");
szamolando.put(kimenet, outputs);
}
than i've got this output: 1 2 3 2
why do i got this?What is wrong with my method?Thank You for your answers!
Edit:
okay here is the complete code:
public static Map<String, ArrayList<String>> szamolando = new HashMap<String, ArrayList<String>>();
static ArrayList<String> outputs = new ArrayList<String>();
static String min, max;
public static void main(String[] args) {
for (int i = 0; i < 2; i++) {
if (i == 0) {
min = "10";
max = "20";
} else {
min = "9";
max = "8";
}
tombFeltolt("a" + i);
}
for (String name : szamolando.keySet()) {
String key = name.toString();
String value = szamolando.get(name).toString();
System.out.println("ASS " + key + " " + value);
}
}
public static void tombFeltolt(String kimenet) {
outputs.clear();
System.out.println("1");
outputs.add(min);
System.out.println("2");
outputs.add(max);
System.out.println("3");
outputs.add("65535");
szamolando.put(kimenet, outputs);
}
and here is my output:
ASS a0 [9, 8, 65535]
ASS a1 [9, 8, 65535]

you have to change this:
static ArrayList<String> outputs = new ArrayList<String>();
to this:
static ArrayList<String> outputs = null;
and put this line into your 'for' loop:
outputs = new ArrayList<String>();

This is the source of your problem
When you do a clear, it will clear the ArrayList which still references to the existing ArrayList which will clear the stored list as well coz it has stored the reference.
if you want 10, 20, 65535 use new list everytime.
outputs.clear();

Related

Push An ArrayList of Strings Into HashMap

I am trying to split each element of an ArrayList into a char and double and push the results into a HashMap. So far, my code is this:
public static int TotalAmount(ArrayList<String> x) {
HashMap<Character,Double> hm = new HashMap<Character,Double>();
for(int i = 0; i < x.size(); i++) {
String[] s = x.get(i).split("(?<=\\d)(?=[a-zA-Z])");
hm.put(s[1].charAt(0), Double.parseDouble(s[0]));;
}
I do this with the ArrayList holding:
234K
1.3M
2.1M
211H
11K
But when I iterate through the HashMap, I get:
H, 211
K, 11
M, 2.1
I cannot seem to find where my logic went wrong. I might be able to accredit this to my intro to HashMaps. How do I ensure that I convert the ArrayList of Strings into a HashMap correctly?
To clear things up, I'm trying to completely move the ArrayList into a HashMap, without overwriting when the same key is found.
You can try this:
public static HashMap<Character, List<Double>> TotalAmount(ArrayList<String> initialList) {
HashMap<Character, List<Double>> resultMap = new HashMap<>();
for (String line : initialList) {
Double size = Double.parseDouble(line.substring(0, line.length() - 1));
Character sizeChar = line.charAt(line.length() - 1);
if (resultMap.containsKey(sizeChar)) {
resultMap.get(sizeChar).add(size);
} else {
resultMap.put(sizeChar, Collections.singletonList(size));
}
}
return resultMap;
}
Try this! I tested and it works fine! As QBrute mentioned, HashMap's put() overrides any value that is processed with the same key earlier.
I created method and the test(in main) using HashMap>
.
import java.util.*;
public class Question {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("234K");
list.add("1.3M");
list.add("2.1M");
list.add("221H");
list.add("11K");
HashMap<Character, ArrayList<Double>> result = TotalAmount(list);
System.out.println("K: " + result.get('K'));
System.out.println("M: " + result.get('M'));
System.out.println("H: " + result.get('H'));
}
public static HashMap<Character, ArrayList<Double>> TotalAmount(
ArrayList<String> x) {
HashMap<Character, ArrayList<Double>> map = new HashMap<>();
for (String line : x) {
Double num = Double.parseDouble(line.substring(0,
line.length() - 1));
Character c = line.charAt(line.length() - 1);
if (map.containsKey(c)) {
map.get(c).add(num);
} else {
ArrayList<Double> newList = new ArrayList<>();
newList.add(num);
map.put(c, newList);
}
}
return map;
}
}

[Hackerrank][Performance Improvement] Similar Destinations

I am currently solving a challenge that I found on Hackerrank and am in need of some assistance in the code optimization/performance department. I've managed to get my code working and returning the right results but it is failing at the final test case with a timeout error. The input is quite large so, that explains why the code is taking longer that expected.
Problem statement: Similar Destinations
I've attempted to think of different ways of pruning my (intermediate) result set but could not come up with something that I did not already have. I believe that the find function could use a bit more tweaking. I've tried my best to reduce the number of paths that the recursive function has to take but ultimately, it has to look at every destination in order to come up with the right results. However, I did terminate a recursive path if the number of tags in common between destinations were below the min limit. Is there anything else that I could do here?
My code is as follows:-
static class Destination {
String dest;
List<String> tags;
public Destination(String dest, List<String> tags) {
this.dest = dest;
this.tags = tags;
}
#Override
public String toString() {
return dest;
}
}
static List<Destination> allDest = new ArrayList<Destination>();
static int min;
static Set<String> keysTracker = new HashSet<String>();
static Set<String> tagsTracker = new HashSet<String>();
static Map<String, List<String>> keysAndTags = new HashMap<String, List<String>>();
static void find(List<String> commonKey, List<String> commonTags, int index) {
if (index >= allDest.size())
return;
if (commonTags.size() < min)
return;
if (tagsTracker.contains(commonTags.toString()) || keysTracker.contains(commonKey.toString())) {
return;
}
String dest = allDest.get(index).dest;
commonKey.add(dest);
for (int i = index + 1; i < allDest.size(); ++i) {
List<String> tempKeys = new ArrayList<String>(commonKey);
List<String> tags = allDest.get(i).tags;
List<String> tempTags = new ArrayList<String>(commonTags);
tempTags.retainAll(tags);
find(tempKeys, tempTags, i);
if (tempTags.size() >= min) {
if (!tagsTracker.contains(tempTags.toString())
&& !keysTracker.contains(tempKeys.toString())) {
tagsTracker.add(tempTags.toString());
keysTracker.add(tempKeys.toString());
StringBuilder sb = new StringBuilder();
for (int j = 0; j < tempKeys.size(); ++j) {
sb.append(tempKeys.get(j));
if (j + 1 < tempKeys.size())
sb.append(",");
}
keysAndTags.put(sb.toString(), tempTags);
}
}
}
}
public static void main(String[] args) {
init();
sort();
calculate();
answer();
}
static void init() {
Scanner s = new Scanner(System.in);
min = s.nextInt();
s.nextLine();
String line;
while (s.hasNextLine()) {
line = s.nextLine();
if (line.isEmpty())
break;
String[] tokens = line.split(":");
String dest = tokens[0];
tokens = tokens[1].split(",");
List<String> tags = new ArrayList<String>();
for (int j = 0; j < tokens.length; ++j)
tags.add(tokens[j]);
Collections.sort(tags);
Destination d = new Destination(dest, tags);
allDest.add(d);
}
s.close();
}
static void sort() {
Collections.sort(allDest, new Comparator<Destination>() {
#Override
public int compare(Destination d1, Destination d2) {
return d1.dest.compareTo(d2.dest);
}
});
}
static void calculate() {
for (int i = 0; i < allDest.size() - 1; ++i) {
find(new ArrayList<String>(), new ArrayList<String>(allDest.get(i).tags), i);
}
}
static void answer() {
List<Map.Entry<String, List<String>>> mapInListForm = sortAnswer();
for (Map.Entry<String, List<String>> entry : mapInListForm) {
System.out.print(entry.getKey() + ":");
for (int i = 0; i < entry.getValue().size(); ++i) {
System.out.print(entry.getValue().get(i));
if (i + 1 < entry.getValue().size())
System.out.print(",");
}
System.out.println();
}
}
static List<Map.Entry<String, List<String>>> sortAnswer() {
List<Map.Entry<String, List<String>>> mapInListForm =
new LinkedList<Map.Entry<String, List<String>>>(keysAndTags.entrySet());
Collections.sort(mapInListForm, new Comparator<Map.Entry<String, List<String>>>() {
public int compare(Map.Entry<String, List<String>> e1, Map.Entry<String, List<String>> e2) {
if (e1.getValue().size() > e2.getValue().size()) {
return -1;
} else if (e1.getValue().size() < e2.getValue().size()) {
return 1;
}
return e1.getKey().compareTo(e2.getKey());
}
});
return mapInListForm;
}
Any help is greatly appreciated. Thanks!
I've managed to solve the problem after a bit of selective profiling. It would seem that my initial hunch was right. The problem had less to do with the algorithm and more towards the data structures that I was using! The culprit was in the find method. Specifically, when calling the retainAll method on two lists. I had forgotten the that it would take O(n^2) time to iterate through two lists. That was why it was slow. I then changed list into a HashSet instead. As most of us know, a HashSet has an O(1) time complexity when it comes to accessing its values. The retainAll method stayed but instead of finding the intersection between two lists, we now find the intersection between two sets instead! That managed to shave off a couple of seconds off of the total elapsed runtime and all the tests passed. :)
The find method now looks like this:-
static void find(List<String> commonKey, List<String> commonTags, int index) {
if (index >= allDest.size())
return;
if (commonTags.size() < min)
return;
if (tagsTracker.contains(commonTags.toString()) || keysTracker.contains(commonKey.toString())) {
return;
}
String dest = allDest.get(index).dest;
commonKey.add(dest);
for (int i = index + 1; i < allDest.size(); ++i) {
List<String> tempKeys = new ArrayList<String>(commonKey);
List<String> tags = allDest.get(i).tags;
Set<String> tempTagsSet1 = new HashSet<String>(commonTags);
Set<String> tempTagsSet2 = new HashSet<String>(tags);
tempTagsSet1.retainAll(tempTagsSet2);
List<String> tempTags = new ArrayList<String>(tempTagsSet1);
if (tempTags.size() >= min)
Collections.sort(tempTags);
find(tempKeys, tempTags, i);
if (tempTags.size() >= min) {
if (!tagsTracker.contains(tempTags.toString())
&& !keysTracker.contains(tempKeys.toString())) {
tagsTracker.add(tempTags.toString());
keysTracker.add(tempKeys.toString());
StringBuilder sb = new StringBuilder();
for (int j = 0; j < tempKeys.size(); ++j) {
sb.append(tempKeys.get(j));
if (j + 1 < tempKeys.size())
sb.append(",");
}
keysAndTags.put(sb.toString(), tempTags);
}
}
}
}

Compare all values of arraylist to a string

I have an array list abc which has certain values -
ArrayList< String > abc = new ArrayList<>();
abc.add("hi");
abc.add("hello Yash");
abc.add("i am Yash");
String x = "Yash";
Now, I want to know if x is contained in any of the elements of abc.
If it is, then get the index of the elements which contain x.
Here is a simple solution:
public class FindText
{
public static void main(String[] args)
{
ArrayList< String > abc = new ArrayList<>();
abc.add("hi");
abc.add("hello Yash");
abc.add("i am Yash");
String x = "Yash";
for(int i=0; i<abc.size(); i++)
{
if(abc.get(i).contains(x))
{
int index = i;
System.out.println(index);
}
}
}
}
It gives you 1 and 2 as indexes which includes the text "Yash"
You can achieve this in 2 different ways...
The old school
and the lambdas way
Old school Example:
public static void main(String[] args) {
List<String> abc = new ArrayList<>();
abc.add("hi");
abc.add("hello Yash");
abc.add("i am Yash");
String x = "Yash";
List<String> resultOldSchool = new ArrayList<>();
for (String sentence : abc) {
if (sentence.contains(x)) {
resultOldSchool.add(sentence);
}
}
System.out.println(resultOldSchool);
}
Lambdas way Example:
public static void main(String[] args) {
List<String> abc = new ArrayList<>();
abc.add("hi");
abc.add("hello Yash");
abc.add("i am Yash");
String x = "Yash";
List<String> resultJava8 = findStringInList(abc, x);
if (!resultJava8.isEmpty()) {
System.out.println(resultJava8);
}
}
public static List<String> findStringInList(final List<String> list, final String strng) {
return list.stream().filter(s -> s.contains(strng)).collect(Collectors.toList());
}
feel free to decide....
Assuming that abc is a List<String> and x is a String then this should do the trick.
List<Integer> indexes = new LinkedList<Integer>();
for(int i = 0; i < abc.size(); i++)
{
if(abc.get(i).contains(x))
indexes.add(i);
}
After the loop finishes all the indexes of the elements that contain x will be in the indexes list.

comparing values of two arrays if exist or not

I have this code which is to check in the two arrays and print out the values that dont exist in the other array. I think the way i did it is not the most efficient way to do it hence can anyone offer a better OOP way to write this code in Java?
Thanks
public class Calculate {
static int [] x = {1,2,4,6,7};
static int [] y = {2,3,4,6,7};
static boolean xflag = true;
static boolean yflag = true;
public static void main(String[] args) {
// TODO Auto-generated method stub
for(int i = 0; i<x.length; i++)
{
for (int b=0; b<y.length; b++)
{
if(x[i]!= y[b])
{
xflag= false;
}
else
{
xflag = true;
break;
}
}
if(xflag==false)
{
System.out.println(x[i] +" does not exist in array 2");
}
}
for(int i = 0; i<x.length; i++)
{
for (int b=0; b<y.length; b++)
{
if(y[i]!= x[b])
{
yflag= false;
}
else
{
yflag = true;
break;
}
}
if(yflag==false)
{
System.out.println(y[i] +" does not exist in array1");
}
}
}
}
Using Collection class removeAll method
String original[] = { "1","2","3","4","6"};
String testStr[] = { "1","2","3","5","7" };
List origList = new ArrayList(Arrays.asList(original));
List testList = new ArrayList(Arrays.asList(testStr));
System.out.println(origList.removeAll(testList));
System.out.println(origList);
you can use java collection framework, Many function are there,
here is simple example check it.
public static void main(String a[]){
List<String> sl = new ArrayList<String>();
sl.add("apple");
sl.add("java");
sl.add("c++");
sl.add("unix");
sl.add("orange");
sl.add("airtel");
List<String> tl = new ArrayList<String>();
tl.add("job");
tl.add("oracle");
tl.add("jungle");
tl.add("cricket");
boolean isCommon = Collections.disjoint(sl,tl);
System.out.println("Does not found any common elements? "+isCommon);
tl.add("java");
isCommon = Collections.disjoint(sl,tl);
System.out.println("Does not found any common elements? "+isCommon);
}
You may use Apache's CollectionUtils for this purpose if you want an abstraction from the implementation logic.E.g:
public static void main(String[] args) {
List<Integer> list1=Arrays.asList(1,2,4,6,7);
List<Integer> list2=Arrays.asList(2,3,4,6,7);
System.out.println(CollectionUtils.disjunction(list1,list2));
}
You can code this way
List<Integer> array1 = Arrays.asList(1,2,4,6,7);
List<Integer> array2 = Arrays.asList(2,3,4,6,7);
List<Integer> disjointArray = new ArrayList<Integer>();
for (Integer value : array1) {
if (!array2.contains(value)) {
disjointArray.add(value);
}
}
And then you can print disjointArray or do whatever manipulation you want.
Here a running example using Javas Collection classes:
public class Disjunction {
public static void main(String args[]) throws UnsupportedEncodingException {
//Some data preparation
List<Integer> list1=Arrays.asList(1,2,4);
List<Integer> list2=Arrays.asList(5,2,8);
//Here calculating data1-data2 and data2-data1, collect all list items
//that are in data1 or in data2 but not in both.
List<Integer> data1 = new ArrayList<>(list1);
data1.removeAll(list2);
List<Integer> data2 = new ArrayList<>(list2);
data2.removeAll(list1);
//Merging both results. data1 contains now exclusive or of list1 and list2
data1.addAll(data2);
System.out.println("exclusive or is " + data1);
}
}
It prints out
exclusive or is [1, 4, 5, 8]
Try the following program that checks two arrays for numbers they both have and numbers they don't have:
package test;
import java.util.ArrayList;
public class ArrayDifferentiater {
public static void main(String[] args) {
int[] ori = { 1, 5, 4, 8, 6, 65, 16, 6, 575, 64, 561, 57, 57 };
int[] che = { 1, 4, 8, 6 };
sort(ori, che);
}
public static void sort(int[] a, int[] b) {
/**
* 'foundNum' contains the numbers which exists in both array.
* 'notFoundNum' contains the numbers which exists in only first array.
*/
ArrayList<Integer> foundNum = new ArrayList<>();
ArrayList<Integer> notFoundNum = new ArrayList<>();
// First for loop starts
for (int i = 0; i < a.length; i++) {
// Second for loop starts
for (int j = 0; j < b.length; j++) {
/**
* Check if array 1 contains value of array 2.
* If contains than add it to "foundNum" arraylist.
*/
if (a[i] == b[j]) {
foundNum.add(a[i]);
// Remove the number which exists in both arrays from "notFoundNum" arraylist.
if (notFoundNum.contains(a[i])) {
for (int k = 0; k < notFoundNum.size(); k++) {
if (notFoundNum.get(k) == a[i]) {
notFoundNum.remove(k);
}
}
}
break;
} // First if block ends
/**
* Checks if a not found number does not exists in 'notFoundNum' arraylist (to reduce redundancy)
* then adds a not found number to 'notFoundNum' arraylist
* */
if (!notFoundNum.contains(a[i]))
notFoundNum.add(a[i]);
} // Second for loop ends
} // First for loop ends
System.out.println("Found Numbers : " + foundNum);
System.out.println("Not Found Numbers : " + notFoundNum);
}
}
Here is the output for the above program:
Found Numbers : [1, 4, 8, 6, 6]
Not Found Numbers : [5, 65, 16, 575, 64, 561, 57]

Problems with calling a member of array of strings

With the help of the community i managed to get this problem solved: How to convert String to the name of the Array?
But now i get 'nullPointerExceptions'. Here is the code i use:
public class IroncladsAdder
{
public static String weaponId = null;
public static String ship = null;
public static String wing = null;
//map code
private static Map<String, List<Integer>> arrays = new HashMap<String, List<Integer>>();
public void Holder(String... names) {
for (String name : names) {
arrays.put(name, new ArrayList<Integer>());
}
}
//adds weapons to fleets and stations
public static void AddWeapons(CargoAPI cargo, String fac, int count, int type) {
String arrayName = null;
int quantity = (int) (Math.random()*5f + count/2) + 1;
if (count == 1) {quantity = 1;}
if (type == 0) {arrayName = fac+"_mil_weps";}
else if (type == 1) {arrayName = fac+"_civ_weps";}
else {arrayName = fac+"_tech_weps";}
List<Integer> array = arrays.get(arrayName);
for (int j = 0; j <= count; j++)
{
weaponId = valueOf(arrays.get(arrayName).get((int) (Math.random() * arrays.get(arrayName).size())));
cargo.addWeapons(weaponId, quantity);
}
}
Here is an example of the array:
//high-tech UIN weapons
private static String [] uin_tech_weps =
{
"med-en-uin-partpulse",
"lrg-en-uin-partacc",
"med-bal-uin-driver",
"lrg-bal-uin-terminator",
"lrg-bal-uin-hvydriver",
"lrg-bal-uin-shotgundriver",
"lrg-en-uin-empbeam",
};
Error indicates that something is wrong with this construction:
weaponId = valueOf(arrays.get(arrayName).get((int) (Math.random() * arrays.get(arrayName).size())));
NOTE: i`m using Intellij IDEA and Java 6. Application most of the time has advices/fixes for some errors and in this case shows that everything is ok.
What i need is to get a String out of the specific array (that is using a code-generated name) and assign it to 'weaponId'.
When your application start the map with the arrays is empty, then when you try to get the array with name X you get back a null value.
First solution: at startup/construction time fill the map with empty arrays/List for all the arrays names.
Second solution: use this method in order to obtain the array.
protected List<Integer> getArray(String arrayName) {
List<Integer> array = map.get(arrayName);
if (array == null) {
array = new ArrayList<Integer>();
map.put(arrayName, array);
}
return array;
}
P.s.
You can change this code:
weaponId = valueOf(arrays.get(arrayName).get((int) (Math.random() * arrays.get(arrayName).size())));
into
weaponId = valueOf(array.get((int) (Math.random() * array.size())));
Ok. Now there is a different error - 'java.lang.IndexOutOfBoundsException: Index: 0, Size: 0'
Made the code look like this:
private static Map <String, List<Integer>> arrays = new HashMap<String, List<Integer>>();
public static List<Integer> getArray(String arrayName) {
List<Integer> array = arrays.get(arrayName);
if (array == null) {
array = new ArrayList<Integer>();
arrays.put("rsf_civ_weps", array);
arrays.put("rsf_mil_weps", array);
arrays.put("rsf_tech_weps", array);
arrays.put("isa_civ_weps", array);
arrays.put("isa_mil_weps", array);
arrays.put("isa_tech_weps", array);
arrays.put("uin_mil_weps", array);
arrays.put("uin_tech_weps", array);
arrays.put("uin_civ_weps", array);
arrays.put("xle_civ_weps", array);
arrays.put("xle_mil_weps", array);
arrays.put("xle_tech_weps", array);
}
return array;
}
This is how i now call the array and weaponId:
List<Integer> array = arrays.get(arrayName);
for (int j = 0; j <= count; j++)
{
weaponId = valueOf(array.get((int) (Math.random() * array.size())));
cargo.addWeapons(weaponId, quantity);
}
What`s wrong?

Categories

Resources