Adding duplicate values to ArrayList - java

Stackoverflow.
I'm trying to add 4 of each words in my ArrayList into the ArrayList itself. I have in my ArrayList two Strings. One is "java" and the other one is "Program". I'm trying to write a program that adds a total of 4 words of each word. Ex: I'm trying to add 4 x java and 4 x program.
Here's what I've got so far. I have no idea, what I'm doing wrong.
Any help or hints would be much appreciated.
/*
* Write a method called quadList that takes an ArrayList of strings as a parameter
* and replaces every string with four of that same string.
* For example, if the list stores the values ["java", "program"]
* before the method is called,it should store the values
* ["java ", " java ", " java ", " java ", "program", "program", "program", "program"]
* after the method finishes executing.
*/
import java.util.ArrayList;
public class Ex10_4_quadList {
public static void main(String[] args) {
ArrayList<String> arrList = new ArrayList<String>();
arrList.add("Java");
arrList.add("Program");
System.out.println("Before: " + arrList);
quadList(arrList);
System.out.println("after " + arrList);
}
private static void quadList(ArrayList<String> list) {
for (int i = 0; i < list.size(); i++) {
for (int j = 0; j < 4; j++) {
String temp = list.get(i);
list.add(temp);
}
}
}
}
Here's the fixed code:
public class Ex10_4_quadList {
public static void main(String[] args) {
ArrayList<String> arrList = new ArrayList<String>();
arrList.add("Java");
arrList.add("Program");
System.out.println("Before: " + arrList);
quadList(arrList);
Collections.sort(arrList);
System.out.println("after " + arrList);
}
private static void quadList(ArrayList<String> list) {
int initial = list.size();
for (int i = 0; i < initial; i++) {
for (int j = 0; j < 3; j++) {
String temp = list.get(i);
list.add(temp);
}
}
}
}

Ideally instead of iterating with an index you would use the foreach style of loop. However this means that you can't alter the list as you iterate. So you will need to add the members to a new list and then add all of them afterwards:
List<String> duplicates = new ArrayList<>();
for (String member: list) {
for (int i = 0; i < 4; i++) {
duplicates.add(member);
}
}
list.addAll(duplicates);
There are a number of shortcuts you can use if you are using Java 8 and, therefore, have access to streams:
list.addAll(list.stream()
.flatMap(m -> Stream.generate(() -> m).limit(4))
.collect(Collectors.toList());
This code says for each member of the list turn it into 4 copies of the item then collect all those as a list and add them to the original list.

Try:
private static void quadList(ArrayList<String> list) {
int listSize = list.size();
for (int i = 0; i < listSize; i++) {
for (int j = 0; j < 4; j++) {
String temp = list.get(i);
list.add(temp);
}
}
}
The problem with the code is that the list.size() is evaluated on every iteration. Since the inner loop is increasing the list size faster than the outer loop can iterate over it, the code effectively loops infinitely until JVM runs out of memory.

Related

Array output repeating one more then it should

This code basically takes a string array goes through it one at a time and displays a tally of each elements occurrence.
problem is that element number 3 ("One") is repeated at the end and im not sure why, so the out put i would get is:
Current Output:
One 2
Two 1
Three 1
One 2
Code:
public static void main(String[] args) {
String [] myStrings = {"One", "Two", "Three", "One"};
StringCount(myStrings);
}
public static void StringCount(String [] Array)
{
int size = Array.length;
for (int i = 0; i < size; i++)
{
int count = 0;
String element = Array[i];
for (int j = 0; j < size; j++)
{
if (Array[j].equals(element)){
count ++;
}
}
System.out.println(Array[i] + " " + count);
}
}
Expected Output:
One 2
Two 1
Three 1
First, you get four printed lines because you call the output method inside a loop that runs exactly four times:
for (int i = 0; i < size; i++) // size is 4
{
...
System.out.println(Array[i] + " " + count);
}
As you want to count the occurrences of all distinct strings, you want to map those strings to their count. The problem is that you can't know the exact number of distinct strings beforehand. So you have to build up such a map and loop again over its elements (in a second step):
Map<String, Integer> counts = new HashMap<>();
/* setup map */
for (int i = 0; i < size; i++) {
String element = Array[i];
/* special case for having an element the first time: */
if (!counts.containsKey(element)) {
counts.put(element, Integer.valueOf(0));
}
/* increase the count for the element and store it back in map */
int oldCount = counts.get(element).intValue();
counts.put(element, Integer.valueOf(oldCount+1));
}
/* print out values */
for(String element : counts.keySet()) {
System.out.println(element + " " + counts.get(element));
}
Use a Set to avoid duplicates like below:
public static void StringCount(String [] Array)
{
int size = Array.length;
Set<String> existingElement = new HashSet<>();
for (int i = 0; i < size; i++)
{
int count = 0;
String element = Array[i];
for (int j = 0; j < size; j++)
{
if (Array[j].equals(element)){
count ++;
}
}
// This will print the result if and only if the element has not
// already been added into the Set
if (existingElement.add(Array[i])) {
System.out.println(Array[i] + " " + count);
}
}
}
Output:
One 2
Two 1
Three 1
Because you check every element and you have One two times, so it will be checked twice! you need to have a set of checked elements so when you check element you put it in set, and then before checking next element you check if it is in set, if it is, then skip it.

Problems with returning ArrayList

I added Strings "Hello", "Cat", "Dog" into the arraylist called values passed it to the method doubleIt() which should return a list of everything doubled, i.e.
"Hello", "Hello", "Cat", "Cat", "Dog", "Dog"
But all Im getting is []. What could I do wrong here ?
import java.util.*;
public class Addition
{
public static void main(String [] args)
{
List<String> values = new ArrayList<String>();
values.add("Hello");
values.add("Cat");
values.add("Dog");
values = doubleIt(values);
System.out.println(values);
}
public static List<String> doubleIt(List<String> values)
{
List<String> temp = new ArrayList<>();
for(int i = 0; i < temp.size(); i++)
{
temp.add(values.get(i*2));
}
return temp;
}
}
Your first mistake is here...
for(int i = 0; i < temp.size(); i++)
temp.size() will be 0 when it's called the first time, you really should be using a values, but this will cause an IndexOutOfBoundsException
So you could use something like...
for (int i = 0; i < values.size(); i++) {
temp.add(values.get(i));
temp.add(values.get(i));
}
instead
First change your for loop condition from
for(int i = 0; i < temp.size(); i++)
to
for(int i = 0; i < values.size(); i++)
and then add values 2 times each.
Your for loop in doubleIt() was looping up to the wrong list size. And you were trying to multiply a string by 2, instead of adding it twice.
public static List<String> doubleIt(List<String> values)
{
List<String> temp = new ArrayList<>();
for(int i = 0; i < values.size(); i++) // <-- you needed to loop up to the size of the values list, not the temp list
{
temp.add(values.get(i));
temp.add(values.get(i));
}
return temp;
}

ArrayIndexOutOfBoundsException for my PrintList function and I have no idea why

I am writing a really simple program which automatically extends the array when the user reaches the limit of the current array.
The problem is that I am getting a java.lang.ArrayIndexOutOfBoundsException when I run my PrintList method and I really don't know why. It's working perfectly if I use a random number, which is bigger than the array (e.g. 500), but if I use
for (int i = 0; i < stringArray.length; i++)
or
for (int i = 0; i <= stringArray.length; i++)
I get a nasty exception. How do I deal with this and why am I getting it in the first place?
Thanks a lot for your help!
Here's the source code of my program:
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
int index = 0;
String[] randomString = new String[1];
while (index <= randomString.length) {
out.println("Enter your string");
String input = keyboard.next();
randomString[index] = input;
PrintArray(randomString);
index++;
if (index >= randomString.length) {
ExtendArray(randomString);
continue;
}
}
}
public static void ExtendArray(String[] stringArray) {
String[] secondArray = new String[stringArray.length * 2];
// Copy first array into second array
for (int i = 0; i < stringArray.length; i++) {
stringArray[i] = secondArray[i];
stringArray = secondArray;
}
}
public static void PrintArray(String[] stringArray) {
for (int i = 0; i < stringArray.length; i++) {
out.println(" " + stringArray[i]);
}
}
Java does not work in the methods you are trying to employ. Everything in Java is passed by value, unless it is a data point in an object. What you are trying to employ is a pass by reference, which is not possible in Java.
What you are trying to do is an already existing data structure called a Vector: http://docs.oracle.com/javase/7/docs/api/java/util/Vector.html
I would suggest doing this: (not sure if it will work properly, as my current PC doesn't have dev tools):
public static String[] ExtendArray(String[] stringArray) {
String[] secondArray = new String[stringArray.length * 2];
// Copy first array into second array
for (int i = 0; i < stringArray.length; i++) {
secondArray[i] = stringArray[i];
}
return secondArray;
}
then calling it like so in main:
randomString = ExtendArray(randomString);
Relating to vectors, this is how it works in a Vector class:
public void incrementCount(int count){
int increment = (count * 2);
Object newElementData [] = new Object[increment];
for(int i = 0; i < count; i++)
{
newElementData[i] = elementData[i];
}
elementData = new Object[increment];
elementData = newElementData;
}
In this case, elementData is the original array, newElementData is a temp array that acts to up the bounds.
You cant get error on your PrintArray method, you get the error on the line before!
randomString[index] = input;
Because if you do this
index <= randomString.length
The last iteration is out of bounds, String of length 10 has values on 0-9. You have to change the while cycle to
index < randomString.length
Also your ExtendArray method is NOT functional!
You are supposed to swap out the randomString array for a new array with double length. You create a new array and copy the contents of the old one to the new one, but don't do anything with the new array.
I suppose you want the ExtendArray method to return the new array, and set the randomString variable to be the new array.
You need to return your second array from ExtendArray function:
public static String[] ExtendArray(String[] stringArray) {
String[] secondArray = new String[stringArray.length * 2];
// Copy first array into second array
for (int i = 0; i <= stringArray.length; i++) {
stringArray[i] = secondArray[i];
}
return secondArray;
}
and in your main:
randomString = ExtendArray(randomString);
also your while condition should be:
while (index < randomString.length)

How can I make a copy of an iterator in Java?

We have a list of elements and have a very simplistic collision detection where we check every object against every other object.
The check is commutative, so to avoid repeating it twice, we would do this in C++:
for (list<Object>::iterator it0 = list.begin(); it0 != list.end(); ++it0)
{
for (list<Object>::iterator it1 = it0; it1 != list.end(); ++it1)
{
Test(*it0, *it1);
}
}
The key bit here is the copy
it1 = it0
How would you write this in Java?
You can do this with ListIterator:
for(ListIterator<O> outer = list.listIterator(); outer.hasNext() ; ) {
O oVal = outer.next();
for(ListIterator<O> inner = list.listIterator(outer.nextIndex()); inner.hasNext(); ) {
Test(oVal, inner.next());
}
}
For a linked list (which has slow index access) the list.listIterator(index) still needs to iterate to the right place, though.
But this way it is only O(n²) (and you can't get better than this) instead of O(n³) like the index-access in the other answers then. (You might be even faster if you copy your list first to an array, but it is only a constant factor here.)
Of course, if you usually need index-based access (or this iterator-cloning), you would better use an array-based list (or a custom list whose iterator supports cloning).
You cannot copy Java iterators, so you'll have to do it without them:
for(int i=0; i<list.size(); i++){
for(int j=i; j<list.size(); j++){
Test(list.get(i), list.get(j));
}
}
For a linked list (which has slow index access), I think there is a way to do it without incurring in the O(n²) slowdown that Paŭlo mentioned. As long as you don't care about the order the list is visited, you can start the outer loop from the last element and iterate back, and start the inner loop from the first element and iterate forward until the two iterators meet. See iterRevIterator in the code below. The call to list.listIterator(list.size()) is fast because list is a LinkedList, i.e. a doubly-linked list, and accessing the last element does not require iterating through the list.
The difference is not enormous...
iterIndex: 384.59ms sum=29656666
iterIterator: 1.91ms sum=29656666
iterRevIterator: 1.55ms sum=29656666
but still significant.
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.ListIterator;
public class TestIter {
public static int iterIndex(List<Integer> list) {
int sum = 0;
for(int i = 0; i < list.size(); ++i) {
for(int j = i+1; j < list.size(); ++j) {
sum += list.get(i) * list.get(j);
}
}
return sum;
}
public static int iterIterator(List<Integer> list) {
int sum = 0;
for(ListIterator<Integer> outer = list.listIterator(); outer.hasNext() ; ) {
Integer oVal = outer.next();
for(ListIterator<Integer> inner = list.listIterator(outer.nextIndex()); inner.hasNext(); ) {
sum += oVal * inner.next();
}
}
return sum;
}
public static int iterRevIterator(List<Integer> list) {
int sum = 0;
for(ListIterator<Integer> outer = list.listIterator(list.size()); outer.hasPrevious() ; ) {
Integer oVal = outer.previous();
for(ListIterator<Integer> inner = list.listIterator(); inner.nextIndex() <= outer.previousIndex(); ) {
sum += oVal * inner.next();
}
}
return sum;
}
public static void main(String[] args) {
int size = 1000;
int rep = 100;
int sum = 0;
// List<Integer> list = new ArrayList<Integer>();
List<Integer> list = new LinkedList<Integer>();
for (int i = 0; i < size; ++i) {
list.add(i);
}
long startTime = System.currentTimeMillis();
for (int i = 0; i < rep; ++i) {
sum = iterIndex(list);
}
System.out.println("iterIndex: " + (float)(System.currentTimeMillis() - startTime)/rep + "ms sum=" + sum);
startTime = System.currentTimeMillis();
for (int i = 0; i < rep; ++i) {
sum = iterIterator(list);
}
System.out.println("iterIterator: " + (float)(System.currentTimeMillis() - startTime)/rep + "ms sum=" + sum);
startTime = System.currentTimeMillis();
for (int i = 0; i < rep; ++i) {
sum = iterRevIterator(list);
}
System.out.println("iterRevIterator: " + (float)(System.currentTimeMillis() - startTime)/rep + "ms sum=" + sum);
}
}

Java algorithm for all-pairs

Given a collection of integers, what's a Java algorithm that will give all pairs of items as follows..
Given the example collection: [1,3,5], we'd want the output:
[1-1]
[3-3]
[5-5]
[1-3]
[1-5]
[3-5]
Note that ordering is not important, so we want one of [1-3], [3-1] but not both.
This should work with a collection of n numbers, not just the the three numbers as in this example.
Below function should do this
private void printPermutations(int[] numbers) {
for(int i=0;i<numbers.length; i++) {
for (int j=i; j<numbers.length; j++) {
System.out.println("[" + numbers[i] + "-"+ numbers[j] +"]");
}
}
}
Example call to this function
int[] numbers={1,2,3};
printPermutations(numbers);
Sounds like homework...but here it is anyway. Obviously you can do without an ArrayList, etc. - just quick and dirty.
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
int[] input = {1, 3, 5};
ArrayList<String> output = new ArrayList<String>();
int n = input.length;
for (int left = 0; left < n; left++) {
output.add("["+input[left]+"-"+input[left]+"]");
for (int right = left + 1; right < n; right++) {
output.add("["+input[left]+"-"+input[right]+"]");
}
}
System.out.println(output.toString());
}
}
Here's the logic you want.
function subsequences (arr) {
arr.sort ();
var subseqs = [];
for (var i = 0; i < arr.length; ++i) {
for (var j = i; j < arr.length; ++j) {
subseqs.push ("" + arr [i] + "-" + arr [j]);
}
}
return subseqs;
}

Categories