I have an ArrayList (listOfNumbers) which contains a number. I have written a Predicate (guava) which gives me a list of EVEN numbers (evenNumberList) from listOfNumbers. I now want all the ODD numbers copied to a new ArrayList. Wondering if there is a quick way of doing this?
Inside your class, have two instance variables: ArrayList<Integer> oddNumbers and ArrayList<Integer> evenNumbers. Then, your method should look like the following:
public void setEvenOdd(ArrayList<Integer> listOfNumbers) {
ArrayList<Integer> even = new ArrayList<Integer>();
for(Integer i : listOfNumbers) {
if(i % 2 == 0) even.add(listOfNumbers.remove(i));
}
this.evenNumbers = even;
this.oddNumbers = listOfNumbers; // since we removed all even numbers
}
Is this what you were asking for?
Related
Good afternoon everyone, I am currently studying for my Java Final and I have a review exercise that asks the reader to create a program that asks the user to input 10 integers and then to use a method to remove duplicates and display the distinct list. The method is provided for you as well.
I've gotten the majority of the code written, in fact I thought I was done until I realized that the for loop is removing more than just duplicates..
Here is my code:
public class lab25 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
int i;
//Create array list
ArrayList<Integer> numbers = new ArrayList<>();
System.out.println("Please enter 10 numbers!");
//Populate
for(i=0; i<10; i++) {
numbers.add(input.nextInt());
}
System.out.println("Your numbers are: " + numbers.toString());
removeDuplicate(numbers);
System.out.println("The distinct numbers are: " +numbers.toString());
input.close();
}
public static void removeDuplicate(ArrayList<Integer> list) {
int i;
for(i=0; i<list.size(); i++) {
if(list.contains(list.get(i))) {
list.remove(i);
}
}
}
}
Just curious what I have done wrong here? I think my issue might lie in my for loop.. Thanks to all who answer.
list.contains(list.get(i)) always returns true, since the i'th element of the List is contained in the List.
Therefore removeDuplicate is trying to remove all the elements (but you only remove half of them, since after removing the i'th element you skip the new i'th element).
There are many ways to remove duplicates. The most efficient involve using a HashSet. If you want to find duplicates using only List methods, you can check if list.lastIndexOf(list.get(i)) > i.
The expression list.contains(list.get(i)) is always true, since you're asking if the list contains some element from the list. You need to check if list.get(i) is contained in the first i-1 items in the list, which I recommend doing with a loop.
Be aware that a loop with list.remove will run slowly, since removing item i from an ArrayList is done by replacing item i with i+1, then replacing item i+1 with i+2 and so on. This means it takes around length^2 time to make a loop that calls remove in every iteration. The function list.contains has the same problem, as it has to go through the entire list. This may not matter if you have 10 items, but if you had a list with a million items, it would take a long time to run.
The easiest ways is to use Stream.distinct():
public static List<Integer> removeDuplicate(List<Integer> list) {
return list.stream().distinct().collect(Collectors.toList());
}
In case you are free to choose collection, you should use LinkedHashSet instead. It holds ordered unique numbers.
A solution could be this one. I startet at the end of the list that I don't delete indexes the loop has to visit in the future.
public static void removeDuplicate(ArrayList<Integer> list) {
int i = list.size() - 1;
while (i > -1) {
// check for duplicate
for (int j = 0; j < i; j++) {
if (list.get(i) == list.get(j)) {
// is duplicate: remove
list.remove(i);
break;
}
}
i--;
}
}
You are taking the list.get(i) which of course is present in the list, and you will delete all of the values in the end.
You could remove them by using a set:
Set<String> hs = new HashSet<>();
hs.addAll(numbers);
numbers.clear();
numbers.addAll(hs);
If you want to keep the current order and do not want to use set.
List<String> notduplicatedList =
new ArrayList<>(new LinkedHashSet<>(String));
I have the following code which sorts a mixed array of items while maintaining the position of types:
For example:
[20, "abc", "moose", 2,1] turns into [1, "abc", "moose", 2, 20]
Algorithm:
public class Algorithm {
public static String[] sortMixedArray(String[] input){
if (input.length == 0){
return input;
}
// make new arraylist for strings and numbers respectively
List<String> strs = new ArrayList<String>();
List<Integer> numbers = new ArrayList<Integer>();
// add values to the arraylist they belong to
for (String item : input){
if (NumberUtils.isNumber(item)){
numbers.add(Integer.valueOf(item));
} else {
strs.add(item);
}
}
// sort for O(nlogn)
Collections.sort(strs);
Collections.sort(numbers);
// reuse original array
for (int i = 0; i < input.length; i++){
if (NumberUtils.isNumber(input[i])) {
input[i] = String.valueOf(numbers.remove(0));
} else {
input[i] = strs.remove(0);
}
}
return input;
}
public static void main(String[] args) {
String[] test = new String[] {"moo", "boo"};
System.out.println(Arrays.toString(sortMixedArray(test)));
}
I have a two-part question:
1. Is switching between array and arraylist efficient? That is, should I have used arrays everywhere instead of arraylist if my input MUST be an array.
2. What is the best way to place arraylist items back into a array? I am checking for type, is there a better way?
1.If you do it the way you have it in your code then it's perfectly fine. If you know beforehand how many elements you will have it's better to use arrays but thats not the case in your example.
2.The best and easiest way is to use the toArray() function of the List interface.
ArrayList<String> list = ...;
String[] array = list.toArray(new String[list.size()]);
But this won't work for your code since you are merging two lists into one array. You can still improve your code a bit because you do not actually have to remove the items from the lists when putting them back in the array. This safes some computation since removing the first element from an ArrayList is very inefficient (O(N) runtime per remove operation).
for (int i = 0, s = 0, n = 0; i < input.length; i++) {
if (NumberUtils.isNumber(input[i])) {
input[i] = Integer.toString(numbers.get(n++));
} else {
input[i] = strs.get(s++);
}
}
No but it highly unlikely to matter unless you have a million of elements.
Do whatever you believe is simplest and most efficient for you, the developer.
BTW the least efficient operations is remove(0) which is O(N) so you might change that.
I am trying to fully understand dynamic programming so I have taken the normal subset sum problem a little further and I am trying to see if I can print out all of the subsets that add to a certain number. As of now I have done it recursively, but I would like to figure out how to do this dynamically. Any help is appreciated. Here is what I have now:
import java.util.ArrayList;
import java.util.HashMap;
import com.sun.xml.internal.bind.v2.schemagen.xmlschema.List;
public class subsetSum {
public static void main (String[] args) {
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(3);
list.add(4);
list.add(0);
printSublists(list, list, 4, true, 0);
}
public static Integer sum(ArrayList<Integer> list) {
Integer sum= 0;
for (Integer i:list)
sum = sum + i;
return sum;
}
public static void printSublists(ArrayList<Integer> list, ArrayList<Integer> list2, int n, boolean walkRight, int level) {
if (sum(list2) == n)
System.out.println(list2);
if (list2.size() == 1)
return;
if (walkRight)
printSublists(list, new ArrayList<Integer>(list2.subList(0, list2.size()-1)), n, walkRight, level+1);
walkRight = false;
printSublists(list, new ArrayList<Integer>(list2.subList(1, list2.size())), n, walkRight, level+1);
}
}
Step 1. Create classes with the following information available:
previousStateTransition:
previousSum
nextAddedElementIndex
countOfWaysHere
sumState:
currentSum
countOfWaysHere
isInitial
previousStateTransitions (array of previousStateTransition objects ordered by nextAddedElementIndex)
Step 2: Implement your DP algorithm, populating the above objects. (This will require a HashMap mapping the current value to the appropriate sumState object.
Step 3: Implement your recursive function that starts with a sumState object and finds all the ways of having gotten there. Be careful as you go backwards to keep track of the nextAddedElementIndex and to stop walking previousSumTransitions when you reach or exceed the last element that is part of the current sum.
Note, both objects include a countOfWaysHere. At the end, the sumState objects have the count of ways to this eventual final sum, while the previousSumTransition objects let you know the counts of ways that you could have gotten to the current sum within the first k elements.
Make sure to test it!
**I want to know how to create an array in run time in java? For an instance say that i want to check the numbers which divides 498 ,and i want to put them into an array ?
for(i=1;i<=498/2;i++){
int z=498%i;
if(z==o)// put the i into the array if not continue
you can create an ArrayList while iterating for loop and later you can convert it to Array like below if you need an array at the end of process
integer [] myNumbers = list.toArray(new Integer[list.size()]);
this will help you not worrying about re sizing of Array at runtime
so finally your code should look like following
List<Integer> numbers = new ArrayList<Integer>();
for(i=1;i<=498/2;i++){
int z=498%i;
if(z==o){
numbers.add(i);
}
}
int [] myNumbers = numbers.toArray(new Integer[numbers.size()]);
import java.io.*;
import java.util.*;
public class Solution {
public static void main(String[] args) {
Scanner scan= new Scanner(System.in);
int size=scan.nextInt(); //Enter size of array
int[] array = new int[size]; //create array at runtime
}
}
int[] numbers = new int[SIZE_OF_ARRAY_HERE];
Or if you want to be able to resize it use an ArrayList instead.
I understand that by "at runtime", you mean that you don't know the size of an array at the beginning, and want the array to grow if needed (correct me if I'm wrong). You can use ArrayList for this:
Declare your list first:
List<Integer> myList = new ArrayList<Integer>();
Use it in your loop:
for (int i=1; i<=498/2; i++) {
int z = 498 % i;
if (z == 0) {
//add i to the list
myList.add(i);
}
}
You can then print the list with:
System.out.println(myList.toString());
Please read about ArrayLists here, or just google it, there's plenty tutorials on ArrayLists.
I have 3 arraylist each have size = 3 and 3 arrays also have length = 3 of each. I want to copy data from arraylists to arrays in following way but using any loop (i.e for OR for each).
myArray1[1] = arraylist1.get(1);
myArray1[2] = arraylist2.get(1);
myArray1[3] = arraylist3.get(1);
I have done it manually one by one without using any loop, but code appears to be massive because in future I'm sure that number of my arraylists and arrays will increase up to 15.
I want to copy the data from arraylists to arrays as shown in the image but using the loops not manually one by one?
How about this?
List<Integer> arraylist0 = Arrays.asList(2,4,3);
List<Integer> arraylist1 = Arrays.asList(2,5,7);
List<Integer> arraylist2 = Arrays.asList(6,3,7);
List<List<Integer>> arraylistList = Arrays.asList(arraylist0, arraylist1, arraylist2);
int size = 3;
int[] myArray0 = new int[size];
int[] myArray1 = new int[size];
int[] myArray2 = new int[size];
int[][] myBigArray = new int[][] {myArray0, myArray1, myArray2};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
myBigArray[i][j] = arraylistList.get(j).get(i);
}
}
To explain, since we want to be able to work with an arbitrary size (3, 15, or more), we are dealing with 2-dimensional data.
We are also dealing with array and List, which are slightly different in their use.
The input to your problem is List<Integer>, and so we make a List<List<Integer>> in order to deal with all the input data easily.
Similarly, the output will be arrays, so we make a 2-dimensional array (int[][]) in order to write the data easily.
Then it's simply a matter of iterating over the data in 2 nested for loops. Notice that this line reverses the order of i and j in order to splice the data the way you intend.
myBigArray[i][j] = arraylistList.get(j).get(i);
And then you can print your answer like this:
System.out.println(Arrays.toString(myArray0));
System.out.println(Arrays.toString(myArray1));
System.out.println(Arrays.toString(myArray2));
You need to have two additional structures:
int[][] destination = new int [][] {myArray1, myArray2,myArray3 }
List<Integer>[] source;
source = new List<Integer>[] {arraylist1,arraylist2,arraylist3}
myArray1[1] = arraylist1.get(1);
myArray1[2] = arraylist2.get(1);
myArray1[3] = arraylist3.get(1);
for (int i=0;i<destination.length;i++) {
for (int j=0;j<source.length;j++) {
destination[i][j] = source[j].get(i);
}
}
If you cannot find a ready made API or function for this, I would suggest trivializing the conversion from List to Array using the List.toArray() method and focus on converting/transforming the given set of lists to a another bunch of lists which contain the desired output. Following is a code sample which I would think achieves this. It does assume the input lists are NOT of fixed/same sizes. Assuming this would only make the logic easier.
On return of this function, all you need to do is to iterate over the TreeMap and convert the values to arrays using List.toArray().
public static TreeMap<Integer, List<Integer>> transorm(
List<Integer>... lists) {
// Return a blank TreeMap if not input. TreeMap explanation below.
if (lists == null || lists.length == 0)
return new TreeMap<>();
// Get Iterators for the input lists
List<Iterator<Integer>> iterators = new ArrayList<>();
for (List<Integer> list : lists) {
iterators.add(list.iterator());
}
// Initialize Return. We return a TreeMap, where the key indicates which
// position's integer values are present in the list which is the value
// of this key. Converting the lists to arrays is trivial using the
// List.toArray() method.
TreeMap<Integer, List<Integer>> transformedLists = new TreeMap<>();
// Variable maintaining the position for which values are being
// collected. See below.
int currPosition = 0;
// Variable which keeps track of the index of the iterator currently
// driving the iteration and the driving iterator.
int driverItrIndex = 0;
Iterator<Integer> driverItr = lists[driverItrIndex].iterator();
// Actual code that does the transformation.
while (driverItrIndex < iterators.size()) {
// Move to next driving iterator
if (!driverItr.hasNext()) {
driverItrIndex++;
driverItr = iterators.get(driverItrIndex);
continue;
}
// Construct Transformed List
ArrayList<Integer> transformedList = new ArrayList<>();
for (Iterator<Integer> iterator : iterators) {
if (iterator.hasNext()) {
transformedList.add(iterator.next());
}
}
// Add to return
transformedLists.put(currPosition, transformedList);
}
// Return Value
return transformedLists;
}