Grabbing random object from ArrayList is not random - java

I am creating a method where if you pass in a parameter of type Random, then it will return a random object. Here is basically what I am trying to do:
public T choose(Random r) {
int randomInt = r.nextInt(randomList.size()); // randomList is just a instance variable
return randomList.get(randomInt);
}
The random list has this the following strings:[2, 2, 2, 1, 1, 1, 1, c, c, c, a, a, a, a]
Then I made a driver with the following code
for (int i = 0; i < 10; i++) {
System.out.print(rndList.choose(rnd)); // rnd is initialized as a static Random variable
}
However my outputs are not coming out random. I used the debugger and found out that my choose method generates an integer that is relatively low, so it will always print out either 2's or 1's but never c's or a's. I can't figure out why this is happening and help would be greatly appreciated.
EDIT: Problem was solved. I left out alot of detail, but when I called the size() method, that was something I overwrote which had an error which would return a smaller number than I would have liked. Thanks to dtech for noticing my silly mistake. Thank you for everyone who tried to help me!

At first glance nothing seems wrong with the code, so it might just be a random result. But your "Print it and check" method is very unreliable. Just use something like this:
final int N = 10000; // test 10.000 times
HashTable<Object, Integer> count = new HashTable(N);
for(int i=0;i < N;i++){
Object o = rndList.choose(rnd);
count.put(o, (count.get(o)==null?0:count.get(o))+1);
}
for(Map.Entry<Object, Integer> map : count.entrySet()){
System.out.println(String.format("%s: %d", map.getKey().toString(), map.getValue()));
}
This will print on average something like:
2: 1429
1: 2857
c: 2143
a: 2857
Only if the numbers differ creatly you should be concerned.
Also make sure that you use the new Random() constructor, not new Random(somenumber). If you use the latter you will get the same number sequence every time.

send you random initialization code, are you getting exactly the same results each time? are you using a seed to create the Random object?

Here is the code I used. You need to provide more code to see why yours doesn't work.
public class Main<T> {
private List<T> randomList = new ArrayList<T>();
public T choose(Random r) {
int randomInt = r.nextInt(randomList.size()); // randomList is just a instance variable
return randomList.get(randomInt);
}
public static void main(String... args) throws IOException, InterruptedException, ExecutionException {
Main<String> rndList = new Main<String>();
rndList.randomList.addAll(Arrays.asList("2, 2, 2, 1, 1, 1, 1, c, c, c, a, a, a, a".split(", ")));
Random rnd = new Random();
for (int i = 0; i < 10; i++) {
System.out.print(rndList.choose(rnd)); // rnd is initialized as a static Random variable
}
}
}
prints
1ca1caa1a2

Related

Create a data structure with the features of an array in the constructor

I want to create a special list data structure that works like an array, in that it's like a list with values x[0], x[1], ... Any advice would be much appreciated.
I know all of my code isn't perfect I just want to figure out how to fix the one problem I've outlined below. This is some of the code I have:
public class SpecialList {
int[] specialList;
int lengthList;
public SpecialList(int x[]) {
this.lengthList = x.length;
this.specialList = new int[lengthList];
this.specialList = x;
for (int i=0; i<lengthList; i++) {
this.specialList[i] = x[i];
}
}
public SpecialList(SpecialList w) {
this.specialList = w.specialList;
}
public SpecialList doSomething(SpecialList y) {
int len = y.lengthList;
//The line below is an example to show the error I get
System.out.println(y[0]);
//Do some other stuff to the list y
return y;
}
//I test the code with this
public static void main(String[] args) {
SpecialList y = new SpecialList(new int[] {14, 17, 30});
SpecialList z = x.doSomething(y);
}
However I get the error 'array required, but SpecialList found' when I try to do stuff with y[i] like with System.out.println(y[0]); line of code.
'lengthList' works but getting the individual values of y[i] , the list doesn't. I cant work out whats wrong with my constructor for it to not work how I want it to.
You can't redefine what [n] means based on what object it's applied to; that's an array-specific notation. So y[0] where y is a SpecialList instance just won't work. If it could work, List (or at least ArrayList or other implementions where direct addressing is cheap) would probably have that feature.
Although you can do that in some other languages, you can't in Java. It's just not a feature Java offers. (Which is a good thing or a bad thing depending on your point of view...) Instead, you'll have to provide get and set methods or similar, just like List does.

Looping and sorting ojbects in a class [duplicate]

This question already has an answer here:
Java Sorting Date field
(1 answer)
Closed 4 years ago.
This is a noob question, sorry, but I am totally confused.
I had created a class called CalendarItems.
The fields are:
int index
String description
String textdate
int daysaway
The constructor uses the first three fields. And for the moment I have created four objects within the class.
I now want to do two things:
Loop through the CalendarItem's
For each CalendarItem calculate daysaway, which is the difference between the text date and today. I have figured out how to calculate this and can manually add do it by calling my method for item1, then for item2, etc
But i'd like to understand how i can do this with a loop. If i was in javascript i'd have an multi-dimensional array and could easy create a loop to cycle through it, but in the scary new world of java I am lost
Sort my CalendarItems on the daysaway field
I want to do this so that I can display them as CardViews in order of soonest-first.
[Inflating CardViews has proved blissfully straight-forward, and I can (again, with a manual 'loop') inflate a card for each CalendarItem and add the various fields to it. And creating the class and fields and adding my 4 sample objects has also worked, so it hasn't been a total lost weekend.]
I think where I am going wrong is that I keep thinking in terms of multi-dimensional arrays from my experience with javascript and Excel VBA, and however much I read about objects and iterator interfaces and arraylists in java, my brain is just refusing to take it in.
I have Google'd a lot on this, but every 'simple guide to iterators' has left me more confused than when I started.
Thanks in advance to anyone patient enough to help me.
I post my solution, as I already wrote it, it should be a complete one:
public class CalendarItem implements Comparable<CalendarItem> {
private int index;
private String description;
private ZonedDateTime textdate;
private long daysAway = 0;
public CalendarItem(int index, String description, ZonedDateTime textdate) {
this.index = index;
this.description = description;
this.textdate = textdate;
this.calculateDaysAway();
}
private void calculateDaysAway() {
this.daysAway = ChronoUnit.DAYS.between(textdate, ZonedDateTime.now(ZoneId.systemDefault()));
}
public long getDaysAway() {
return daysAway;
}
#Override
public int compareTo(CalendarItem o) {
if (this.daysAway < o.daysAway) {
return -1;
} else if (this.daysAway > o.daysAway) {
return 1;
} else {
return 0;
}
}
public static void main(String[] args) {
CalendarItem c1 =
new CalendarItem(0, "One", ZonedDateTime.of(2018, 5, 21, 0, 0, 0, 0, ZoneId.systemDefault()));
CalendarItem c2 =
new CalendarItem(0, "Two", ZonedDateTime.of(2018, 5, 4, 0, 0, 0, 0, ZoneId.systemDefault()));
CalendarItem c3 =
new CalendarItem(0, "Three",ZonedDateTime.of(2018, 5, 11, 0, 0, 0, 0, ZoneId.systemDefault()));
CalendarItem c4 =
new CalendarItem(0, "Four", ZonedDateTime.of(2018, 5, 1, 0, 0, 0, 0, ZoneId.systemDefault()));
List<CalendarItem> calendarItems = new ArrayList<>(Arrays.asList(c1, c2, c3, c4));
Collections.sort(calendarItems);
for (CalendarItem item : calendarItems) {
System.out.println("Item " + item.getDescription() + " is " + item.getDaysAway() + " days away.");
}
}
}
Note: I am using ZonedDateTime from java 8 to represent the date.
For 1) you can either create array in java or you can use ArrayList and store your objects in that arraylist and iterate over arraylist.
ArrayList<CalendarItem> list = new ArrayList();
list.add(obj1); // obj1 is the instance you created for the calendar item.
for(CalendarItem c: list){
// this is loop , do whatever you want here
}
For sorting, Either write a comparator class or implement comparable interface to your CalenderItem and override method compareTo. In this method you can provide comparison logic based on requirede field.
For (1), what have you tried? If you need a multi-dimensional array, nothing stops you from using one. Consider:
int dim1 = 5;
int dim2 = 10; // whatever you need
CalendarItem[][] items = new CalendarItem[dim1][dim2];
Im this case you would iterate your array the same way as with JavaScript.
for (int i = 0; i < dim1; i++) {
for (int j = 0; j < dim2; j++) {
// do whatever you need to do
}
}
You can also read about the enhanced for loop if you don't actually need a numerical index.
For (2) have a look at the Comparator interface in the javadocs as well as the methods in the Collections class, in particolar the sort method.

int cannot be converted to int []

new to programming here and i keep getting the error message, incompatible types, int cannot be converted to int [], the question is to add R1 & R2 together if they are of equal lengths and if not, print a message that says 'the arrays must be same length', if that matters, not sure where im going wrong, any help would be greatly appreciated
public int[] arrayAdd(int[] R1, int[] R2)
{
int[] sumArray= new int[R1.length];
if( R1.length!= R2.length)
{
System.out.println("The arrays must be same length");
}
else
{
for(int i=0; i< R1.length; i++)
for (int j=0; j<R2.length; j++)
{
sumArray= R1[i]+ R2[j]; // Error
}
}
return sumArray;
}
not sure where im going wrong
You are attempting to assign an int to a variable whose type is int[].
That is not legal ... and it doesn't make sense.
This:
sumArray= R1[i]+ R2[j];
should be this
sumArray[something_or_other] = R1[i] + R2[j];
... except that you have a bunch of other errors which mean that a simple "point fix" won't be correct.
Hint: you do not need nested loops to add the elements of two arrays.
sumArray[i]= R1[i]+ R2[j]; // updated line
you need to assign to an array element, but you were doing it wrong.
Your code is broken in many several ways, at least:
You declared returning an array but what is the value of it when inputs are of the wrong size? Manage such errors in better ways (stop, throw exception, return error code, etc). At least never display something at this place, this is not the place were you have to tackle the error, this is the place here you detect it, just report it to caller(s).
You (tried to) created space for the returned value but how could this be if conditions for having a return value is not met?
You used Java syntax to declare an array, int []sumArray should be `int sumArray[0].
You can't dynamically allocate an array like this, to capture a dynamic allocation you must use a pointer, an array is not a pointer. But a pointer can be set to the memory address of an allocated array, like int *sumArray = new int[10]
sumArray is an array so to set an element of it use sumArray[index] = ...
So this may be better:
public int *arrayAdd(int[] R1, int[] R2) {
if( R1.length!= R2.length) {
return nullptr;
}
int *sumArray= new int[R1.length];
for(int i=0; i< R1.length; i++) {
sumArray[i] = R1[i]+ R2[i];
}
return sumArray;
}
After question editing
If you want to sum two arrays, element by element, then a single loop is sufficient...
Actually in that line sumArray is an integer array and you are assigning it as integer only and also you haven't declared variable j.
Try this-
public int[] arrayAdd(int[] R1, int[] R2)
{
int[] sumArray= new int[R1.length];
if( R1.length!= R2.length)
{
System.out.println("The arrays must be same length");
}
else
{
for(int i=0; i< R1.length; i++)
{
sumArray[i]= R1[i]+ R2[i]; // Error
}
}
return sumArray;
}

Creating new objects from array to array

I'm trying to generate new unique objects from an array of all possible objects to another array. The idea is that I have 3 classes that implement Region class and they have their own methods. These 3 classes are in my ArrayList<Region> arr. I pick a random class and add it to ArrayList<Region> ALL_REGIONS in a for loop. The problem is that the object that is added from arr is not unique, they are the same. This ca be told by their name. Every Region must have it's unique name and other settings but they don't. So this is the code I have so far:
public void generateRegions(){
ArrayList<Region> arr = Regions.getAllRegions();
Random rnd = new Random();
String ntype;
int regcounter = 5;
int b;
for(int i = 0; i < regcounter; i++){
ALL_REGIONS.add(arr.get(rnd.nextInt(arr.size())));
ntype = "n" + ALL_REGIONS.get(i).getType();
b = rnd.nextInt(Regions.getNtypeSize(ntype));
UI.print("b: " + b);
ALL_REGIONS.get(i).setName(Regions.getArrayName(ntype, b));
}
}
public static ArrayList<Region> getAllRegions(){
ArrayList<Region> arr = new ArrayList<Region>();
arr.add(new Highlands());
arr.add(new Cave());
arr.add(new Oasis());
return arr;
}
getArrayName returns a String name of the Region from an array and getNtypeSize returns an int, size of the array String[] that contatins all names which is not really important just now.
So.. how can I have every Cave, every Oasis unique/as a separate object?
**EDIT: ** Requested getArrayName() and getNtypeSize() methods are below:
public static String getArrayName(String ntype, int t) {
String ans = null;
if(ntype.equals("ncave")){
if(t<=ncaveSize)
ans = ncave[t];
}else if(ntype.equals("noasis")){
if(t<=noasisSize)
ans = noasis[t];
}else if(ntype.equals("nhighlands")){
if(t<=noasisSize)
ans = nhighlands[t];
}
//Can happen when t is bigger then ntype size or
// if ntype string is wrong
if(ans == null){
UI.printerr("getArrayNames: ans is empty/null");
}
UI.printerr(ans);
return ans;
}
public static int getNtypeSize(String ntype){
int ans = 0;
if(ntype.equals("ncave")){
ans = ncaveSize;
}else if(ntype.equals("noasis")){
ans = noasisSize;
}else if(ntype.equals("nhighlands")){
ans = nhighlandsSize;
}else
UI.printerr("getNtypeSize: returned 0 as an error");
return ans;
}
The issue is in this line:
ALL_REGIONS.add(arr.get(rnd.nextInt(arr.size())));
Here, you're not adding a new object to ALL_REGIONS. Rather, each time you're adding a reference to an object in 'arr'.
For example, each time rnd.nextInt(arr.size()) returns 2, you would add a reference to arr[2] to ALL_REGIONS. Thus, effectively, each entry in ALL_REGIONS refers to one of the objects in arr. (In this specific example, one of 3 objects you added in getAllRegions())
Effectively, this means that every Highlands object reference in ALL_REGIONS points to the same object => arr[0]
Similarly, every Cave reference in ALL_REGIONS points to arr[1] and every Oasis reference points to arr[2]
Something along this line should fix the issue:
Region reg = arr.get(rnd.nextInt(arr.size()))
ALL_REGIONS.add(reg.clone()); // this is just meant to be a sort of pseudo-code. Use a clone() method to create a new copy of the object and that copy to ALL_REGIONS.
If I got it right? You want to cast back to the type of the original object. It is plenty easy to do so, you will use some of the Java Polymorphism concepts.
You will use a function called InstanceOf like this
Region ob = arr[0];
if (ob instanceof Highlands)
Highlands newOb = (Highlands) ob;

Find and print the product of all the entries in array

Okay I have tried to write a simple Java code in BlueJ, that finds and prints the product of all the entries in data such as if data is {1,2,3,4} then the result will be 24.
And my code is below:
public class Product {
public static int[] product(int[] a) {
int [] s = new int[a.length];
for (int i =0; i< a.length; i++)
s[i] = a[i]*a[i];
return s; //the definition of your method...
}
public static void main(String[] args) {
//calling the method to seek if compiles
int[] results = Product.product(new int[] { 1,2,3,4 });
//printing the results
System.out.println(java.util.Arrays.toString(results));
}
}
The above code is giving me the square of each number, which is not what I want to have, somehow I have modify the code that the result will be 24 but I couldn't figure it out, anyone knows how to do it?
First of all, if you are first writing Java it is important to know that variable, function and class names are quite important. Please note that having Product.product() is not a good idea, since the function name is almost the same as the class name. Anyway, regarding your code. Your code is indeed returning the square of your input, what you would want is the following:
public class Product {
public static int getProduct(int[] input) {
int total = 1;
for (int v : input) {
total *= v;
}
return total;
}
}
This will return an integer value with the product of your input array. This also uses a for-each loop instead of a regular for-loop for readability. Also you don't need the index in this case. Good luck with it!
First, your product method needs to return an int rather than an int [].
You need to maintain the product as a variable. You can set it to 1 initially, and then multiply it by each element of the a array in turn; then you just return this value.

Categories