I would like to initialize an ArrayList with a range of integer values.
This is what I want to avoid:
ArrayList<Integer> numbers = new ArrayList<>();
for(int i = 0; i < x; i++){
numbers.add(i);
}
I found rangeClosed function for IntStream:
IntStream.rangeClosed(0, instance.getNumVertices()-1);
But I think that the conversiont to ArrayList won't be worth it.
I'm looking for efficiency...
The ArrayList is backed by an array. If you want to fill it with ascending values, you won't get any quicker than just iterating over those values and adding them to the list.
The only thing I'd change in your example is initialize the array with the already known size, so that it wouldn't spend time and memory on expansion of the underlying array:
ArrayList<Integer> numbers = new ArrayList<>(x);
for(int i = 0; i < x; i++){
numbers.add(i);
}
List<Integer> range100 = IntStream.range(0,100).boxed().collect(Collectors.toList());
If you want to have an object that looks like a List<Integer> that contains numbers from 0 up to N without actually storing those numbers, then you can implement your own list, for example like this:
import java.util.AbstractList;
public class RangeList extends AbstractList<Integer> {
private final int size;
public RangeList(int size) {
this.size = size;
}
#Override
public Integer get(int index) {
return index;
}
#Override
public int size() {
return size;
}
}
You can create an instance of it like this:
List<Integer> numbers = new RangeList(10);
It behaves just like a standard ArrayList<Integer> containing the values 0 to 9, but you cannot modify the list (adding, removing, modifying entries will lead to an UnsupportedOperationException).
No matter how you decide to fill the ArrayList you will have to loop over or use each value that is stored into the ArrayList one by one. There is no faster way then iterating over each value and adding it to the ArrayList, only ways that make it look cleaner.
Creating a function that does so, or a an extension of the ArrayList object are two ways of doing so.
private ArrayList<Integer> fillRange(int min, int max){
ArrayList<Integer> a_lst = new ArrayList<>();
for(int i = min; i < max; i++){
a_lst.add(i);
}
return a_lst;
}
Related
I'm new to Java, and I'm not sure how to ask the right question, so please bear with me. I have 40 total items of 6 different types to put into a new array; each item type has a different cost. The first item (quantity=1) costs $3, the second item (qty=2) costs $5 each, the third item (qty=4) costs $9 each, and so on. The quantity of each item type is in numTypeIndArray and the cost for each type is in costCSDriverArray. A cumulative count of the total items is in numTypeCumulArray.
So, the new array, indItemCostArray, should be single dimensional and have 40 elements. It would look something like {3,5,5,9,9,9,9,...,13,13,13}, but the last fifteen elements are a cost of $13. How do I get to this array with 40 elements? I started with trying to fill the array using a nested for loop but I haven't gotten there yet. The code below is plain wrong.
int[] costArray = new int[]{3,5,9,10,11,13};
int[] numTypeIndArray = new int[]{1,2,4,7,11,15};
int[] numTypeCumulArray = new int[]{1,3,7,14,25,40};
int[] indItemCostArray = new int[numTypeCumulArray[6]];
for (int i = 0; i < indItemCostArray.length; i++) {
for (int j = 0; j < numTypeIndArray[i]; j++) {
indItemCostArray[i+j] = costArray[j];
}
}
First of all, you'll get a ArrayOutOfBoundException at:
int[] indItemCostArray = new int[numTypeCumulArray[6]];
The size of the array numTypeCumulArray is 6, and arrays are 0 indexed. So, The last index number is 5, not 6, as indexing started from 0.
You can do as follows for accessing the last element of the array:
int[] indItemCostArray = new int[numTypeCumulArray[numTypeCumulArray.length - 1]];
Secondly, you're running your outer loop for 40 times and for each iteration your inner loop is trying to iterate for numTypeIndArray[i] times, where i is the iterator variable of outer loop. So, surely after sixth iteration, when value of i will be 6, your program will again throw the ArrayOutOfBoundException as you're accessing a value in the terminator condition of the inner loop from numTypeIndArray whose last index is 5.
Again, inside the inner loop, you're assigning indItemCostArray at index position i+j, which will actually far from your purpose.
To achieve what you are exactly expecting, you can do as follows:
int currentIndex =0;
for (int costIndex = 0; costIndex < costArray.length; costIndex++) {
for(int index = currentIndex; index < currentIndex + numTypeIndArray[costIndex]; index++) {
indItemCostArray[index] = costArray[costIndex];
}
currentIndex = numTypeCumulArray[costIndex];
}
Here, what I did is, in the outer loop I iterated the same amount of time the length of costArray, you can take the length of numTypeIndArray instead too, no issue. I've defined a variable named currentIndex to keep track of the current assignable index for array indItemCostArray. In the inner loop, I tried to begin with the currentIndex and loop upto the time same as the number of items needed for that type, given in numTypeIndArray[costIndex], and for each iteration, set the corresponding index of indItemCostArray with the cost of costIndex in the costArray. Finally, I update the currentIndex with the corresponding cumulative total items from numTypeCumulArray.
Hope you got everything clear.
The whole setup of three arrays is kind of weird. The weiredest is the third array. Think carefully, do you actually need it? You already have all the information in your second array. The third array can introduce a lot of unnacessary mistakes.
But, assuming that you actually need these arrays for some reason and there are no mistakes in making these arrays. You can get your required fourth array as follows,
int[] costArray = new int[]{3,5,9,10,11,13};
int[] numTypeIndArray = new int[]{1,2,4,7,11,15};
int[] numTypeCumulArray = new int[]{1,3,7,14,25,40};
// you want to make sure that your arrays are of same lenght
assert(costArray.length == numTypeIndArray.length && costArray.length == numTypeCumulArray.length);
// length of these arrays is unique items count
int uniqueItemsCount = costArray.length;
// totalItemsCount is last element of numTypeCumulArray
int totalItemsCount = numTypeCumulArray[uniqueItemsCount - 1];
int[] indItemCostArray = new int[totalItemsCount];
// use this to keep track of index in indItemCostArray
int itemCostIndex = 0;
for (int i = 0; i < uniqueItemsCount && itemCostIndex < totalItemsCount; i++) {
for (int j = 0; j < numTypeIndArray[i] && itemCostIndex < totalItemsCount; j++) {
indItemCostArray[itemCostIndex] = costArray[j];
// increase the index for next item cost
itemCostIndex += 1;
}
}
int[] costArray = new int[]{3,5,9,10,11,13};
int[] numTypeIndArray = new int[]{1,2,4,7,11,15};
int[] numTypeCumulArray = new int[]{1,3,7,14,25,40};
int[] indItemCostArray = new int[numTypeCumulArray[5]];
int num = 0;
for (int i = 0; i < numTypeIndArray.length; i++) {
for (int j = 0; j < numTypeIndArray[i]; j++) {
indItemCostArray[num + j] = costArray[i];
}
num += numTypeIndArray[i];
}
System.out.println(Arrays.toString(indItemCostArray));
First, you don't need int[] numTypeCumulArray = new int[]{1,3,7,14,25,40};
It just shows the cumulative values of the numTypeIndArray. The last value, 40 is just the sum of numTypeIndArray and that would be the size of the resulting array from your requirement.
It can be summed in a simple for loop or you can do it like this and then create the target array.
int maxSize = Arrays.stream(numTypeIndArray).sum();
int[] indItemCostArray = new int[maxSize];
Then you could proceed to populate the array with the values as has been shown. Here is another way using streams which you will undoubtedly learn about. The quick explanation is that it creates multiple streams of the proper quantities of cost.
e.g
stream1 -> {3}
stream2 -> {5,5};
stream3 -> {9,9,9,9} etc.
Then it flattens them in a single stream of those values and returns an array.
int[] result = IntStream.range(0, costArray.length)
.flatMap(i -> IntStream.range(0, numTypeIndArray[i])
.map(q -> costArray[i]))
.toArray();
But using a class to hold the information would be better. Here is one example.
class Product {
private String name;
private int cost;
private int quantity;
public Product(String name, int cost, int quantity) {
this.name = name;
this.cost = cost;
this.quantity = quantity;
}
public int getCost() {
return cost;
}
public int getQuantity() {
return quantity;
}
public String getName() {
return name;
}
#Override
public String toString() {
return new StringJoiner(", ","[", "]").add(name).add("cost="+cost).add("quantity="+quantity).toString();
}
}
And it can be used like so.
List<Product> products = new ArrayList<>();
for (int i = 0; i < costArray.length; i++) {
products.add(new Product("Item" + (i+1), costArray[i], numTypeIndArray[i]));
}
products.forEach(System.out::println);
Prints
[Item1, cost=3, quantity=1]
[Item2, cost=5, quantity=2]
[Item3, cost=9, quantity=4]
[Item4, cost=10, quantity=7]
[Item5, cost=11, quantity=11]
[Item6, cost=13, quantity=15]
And once again it can be streamed to create your results exactly as before only using the class getters to get the values.
int[] result2 = products.stream()
.flatMapToInt(
prod -> IntStream.range(0, prod.getQuantity())
.map(q -> prod.getCost()))
.toArray();
The two arrays result and result2 are identical. But you may find that using classes may eliminate the requirement for creating such an array.
I'm trying to sort an ArrayList<> of names using selection sort to sort names alphabetically in both increasing and descending order using my two methods minimumPosition() and maximumPosition(). I'm having trouble comparing the Strings because it says that .compareToIgnoreCase requires an array but an ArrayList<String> was found. I'm not sure of any other way to compare an ArrayList<> to print out my names in both alphabetical orders.
I've tried switching my return method type from int to String but that didn't help, I've also tried switching some of the variable types from int to String just to see if anything would work and it did not. I've searched around the web to find a solution to this, but I've only found how to use selection sort with integers and arrays, not ArrayLists. The ArrayList<> of integers in my code is for the second part of my assignment dealing with linear and binary search, so ignore that. My main focus is with the ArrayList<> of names. Any help would be appreciated, below is a sample of my code.
package classwork_additional1;
import java.util.ArrayList;
import java.util.Collections;
public class Classwork_Additional1 {
public static void main(String[] args){
ArrayList<String> array = new ArrayList<>();
array.add("Mary");
array.add("Mike");
array.add("Michael");
array.add("Ann");
array.add("Tom");
array.add("Tommy");
array.add("Bob");
ArrayList<Integer> integers = new ArrayList<>();
integers.add(10);
integers.add(10);
integers.add(5);
integers.add(8);
integers.add(10);
integers.add(7);
integers.add(10);
}
public static void sort(ArrayList<String> array)
{
for (int i = 0; i < array.size() - 1; i++)
{
int minPos = minimumPosition(array, i);
swap(array, minPos, i);
}
}
public static void swap(ArrayList<String> array, int i, int j)
{
String temp = array.get(i);
array.set(i, array.get(j));
array.set(j, temp);
}
private static int minimumPosition(ArrayList<String> array, int from){
int minPos = from;
for (int i = from + 1; i < array.size(); i++)
{
if (array.get(i).compareToIgnoreCase(array[minPos]) < 0)
minPos = i;
}
return minPos;
}
private static int maximumPosition(ArrayList<String> array, int from)
{
int maxPos = from;
for (int i = from + 1; i < array.size(); i++)
{
if (array.get(i).compareToIgnoreCase(array[maxPos]) > 0)
maxPos = i;
}
return maxPos;
}
I'm expecting the names to appear in alphabetical order starting with "Ann" and going up to "Tommy" and also on another line going from "Tommy" going back down to "Ann".
Simply change
if(array.get(i).compareToIgnoreCase(array[minPos]) < 0)
to
if(array.get(i).compareToIgnoreCase(array.get(minPos)) < 0)
If you are trying to get the element at one specific index two times, why are you trying it with differend approches?
I'm a beginner in Java and trying to get the sum of all the elements in the ArrayList. I'm doing it by using a method and get this error in the method:
"bad operand types for binary operator '+' first type: int, second
type: Object"
I don't know what I'm doing wrong here, appreciate any help!
public static int sumNumbers(<ArrayList> numbers){
int sum = 0;
for(int i = 0; i<numbers.size(); i++){
sum+=numbers.get(i);
}
return sum;
}
As others have pointed out, you need to give your ArrayList a type. You can then use native streams to make the code a little more compact:
ArrayList<Integer> numbers = ... ;
numbers.stream().mapToInt(i -> i).sum();
// create a list
List<Integer> ints = Arrays.asList(1, 2, 3);
// get the sum of the elements in the list
int sum = MathUtils.sum(ints);
Declare numbers as ArrayList<Integer> numbers.
Then the Integer will be unboxed to int. Right now, your arraylist contains objects that may not be ints.
For the moment, numbers.get() will return an object, and you can not add an object to an int directly.
You could always cast the element to Integer, but I would recommend the first option.
This will works fine.
import java.util.ArrayList;
public static int sumNumbers(ArrayList<Integer> numbers){
int sum = 0;
for(int i = 0; i<numbers.size(); i++){
sum+=numbers.get(i);
}
return sum;
}
Or
public static int sumNumbers(ArrayList<Integer> numbers){
return numbers.stream().mapToInt(n->n).sum();
}
I am given a problem in which I have to store a list of N numbers in an array and then sort it ,
and then I have to add the numbers at alternative positions and output the sum.
The problem is the constraint of N i.e 0 <= N <= 1011 so I have to declare the N as double type variable here is my code :
ArrayList<Double> myList = new ArrayList<Double>();
myList.add(number);
.....
Collections.sort(myList);
String tempNo = "";
for(double i = 0 ; i < myList.size() ; i=i+2){
tempNo = myStringWayToAdd(tempNo , myList(i)+""); // Since the sum will exceed the limit of double I have to add the numbers by help of Strings
}
But the problem is that the get(int) method takes an int not double. Is there any other way I can solve the problem? , and Is it even allowed to store number of elements that exceed int range?
Any help will be highly appreciated. Thank you in Advance.
Edit 1 :
I can use Strings instead of double in ArrayList and then add up the numbers but my problem is that i need to store N elements which can exceed the range of Integers
You could use LinkedList because it does not have a size limit (although odd things may begin to happen up there). You should also be able to use BigInteger for your numbers if the numbers themselves could get huge (you don't seem to state).
// LinkedList can hold more than Integer.MAX_VALUE elements,
List<BigInteger> myList = new LinkedList<>();
// Fill it with a few numbers.
Random r = new Random();
for (int i = 0; i < 1000; i++) {
myList.add(BigInteger.probablePrime(10, r));
}
// Sort it - not sure if Collections.sort can handle > Integer.MAX_VALUE elements but worth a try.
Collections.sort(myList);
// Start at 0.
BigInteger sum = BigInteger.ZERO;
// Add every other one.
boolean addIt = false;
for (BigInteger b : myList) {
if (addIt) {
sum = sum.add(b);
}
addIt = !addIt;
}
I am not sure if Collections.sort can handle a list of numbers that big, let alone whether it will succeed in sorting within the age of the universe.
You may prefer to consider a database but again you might even have probelms there with this many numbers.
Ah, I misunderstood the question. So we have to store something that is significantly larger than the capacity of int.
Well, we can do this by dividing and conquering the problem. Assuming this is theoretical and we have unlimited memory, we can create a SuperArrayList.
'Scuse my bad generics, no compiler.
public class SuperArrayList<E>() {
private ArrayList<ArrayList<E>> myList;
private int squareRoot;
private double capacity;
public SuperArrayList(double capacity) {
this.capacity = capacity;
squareRoot = Math.ceil(Math.sqrt(capacity)); //we create a 2d array that stores the capacity
myList = new ArrayList<ArrayList<E>>();
for(int i = 0; i < squareRoot; i++) {
myList.add(new ArrayList<E>());
}
}
public E get(double index) {
if(index >= capacity || index < 0) {
//throw an error
}
else {
return myList.get((int) capacity / squareRoot).get(capacity % squareRoot);
}
}
}
As an alternative to squareRoot, we can do maxValue and add additional arraylists of length maxvalue instead.
boolean add = true;
for (Double doubleNum : myList) {
if (add) {
tempNo = myStringWayToAdd(tempNo , doubleNum+"");
}
add = !add;
}
Using this way, you won't have to use index.
I have an array of linked lists (an adjacency list) most of the lengths of the linked lists are 4 but there are some that will randomly have more than that. My goal is to go through the array and find the ones that are more than length 4 (thats the easy part) then add the index's to an array so something like
for (int i = 0; i < 1000; i++){
if(sWorld[i].length > 4)
//add i to an array
// then sort the array
couldnt really figure out how to do this. i tried to add to a inked list then linked list toArray() but then it was messing up. i just dont really know how to add the 'i' point in my sWorld array to say the first position in the new array im going to use for the ones that are grater than size 4.
Any help would be much appreciated!
EDITED TO CLARIFY A BIT
i need the indexes of the the locations that are size > 4, but then i want to know which of those indexes that i get have the greatest size. Maybe i wasnt 100% clear in my op, but basically im trying to find which of the 1000 indexes in the array have the most connections (the longest linked list) make sense?
I want to know the top 10 connected indexes of the array (aka which 10 have the greatest size of linked list)
You can use an ArrayList to store the indexes:
List<Integer> indexes = new ArrayList<Integer>();
for (int i = 0; i < 1000; i++){
if (sWorld[i].length > 4) {
//add i to a list (not an array yet)
indexes.add(i);
}
...
}
// then sort the list
// not necessary, as indexes are inserted in the right order, but if you must...
// Collections.sort(indexes);
// and, if you need an array instead of a list
Integer[] indexesArray = indexes.toArray(new Integer[indexes.size()]);
A List, or an ArrayList, work as variable-length arrays. Though not as efficiently as an actual array.
As seen above, there is no need to sort the array later, but, if you must, you can use Collections.sort().
Also, if you must have an int[] instead of an Integer[], please check: How to convert List<Integer> to int[] in Java?
Update:
As you want to know the size and index of the bigger arrays, it's a whole new problem. Below is a working code that deals with it.
Basically, everytime you find an array with size larger than 4, you add a pair (index, size) to the list. This list is then ordered by size, in descending order.
At the end of the main() method, an array is created (int[] topTenIndexes) which contains the indexes of the 10 biggest arrays (the indexes are presented in descending order of it's array's length). The result is -1 when there weren't enough big (length > 4) arrays.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class Example {
public static void main(String[] args) {
List<ArrayIndexAndSize> indexes = new ArrayList<ArrayIndexAndSize>();
int[][] sWorld = {{1},{2,5,5,5,5},{3,6,6,6,6,6}};
for (int i = 0; i < sWorld.length; i++){
if (sWorld[i].length > 4) {
// add a pair (index, size) to the list
indexes.add(new ArrayIndexAndSize(i, sWorld[i].length));
}
//...
}
// then sort the list by array SIZE, in descending order
Collections.sort(indexes);
// Print it!
System.out.println(indexes);
/* output:
"[[Array index: 2; Array size: 6], [Array index: 1; Array size: 5]]"
*/
// Generating an array with the top ten indexes
int[] topTenIndexes = new int[10];
Arrays.fill(topTenIndexes, -1);
for (int i = 0; i < indexes.size() && i < 10; i++) {
topTenIndexes[i] = indexes.get(i).index;
}
// Print it
System.out.println(Arrays.toString(topTenIndexes));
/* output: [2, 1, -1, -1, -1, -1, -1, -1, -1, -1] */
}
public static class ArrayIndexAndSize implements Comparable<ArrayIndexAndSize> {
public int index;
public int size;
public ArrayIndexAndSize(int index, int size) {
this.index = index;
this.size = size;
}
/* Order by size, DESC */
/* This is called by Collections.sort and defines the order of two elements */
public int compareTo(ArrayIndexAndSize another) {
int thisVal = this.size;
int anotherVal = another.size;
return -(thisVal<anotherVal ? -1 : (thisVal==anotherVal ? 0 : 1));
}
#Override
public String toString() {
return "[Array index: "+index+"; Array size: "+size+"]";
}
}
}
If you have an array LinkedList<?>[] sWorld (fill the type you're using in for ?), then do this:
ArrayList<Integer> listOfLists = new ArrayList<>();
for (int i=0; i<sWorld.size(); i++) {
if (sWorld[i].size > 4) {
listOfLists.add(i);
}
}
Comparator<Integer> sizeComparator = new Comparator<Integer>() {
public int compare(Integer a, Integer b) {
return Integer.compare(sWorld[a].size(), sWorld[b].size());
}
}
Collections.sort(listOfLists, sizeComparator);