This question already has answers here:
Take n random elements from a List<E>?
(12 answers)
Closed last year.
public class Main {
public static void main(String[] args) {
String[] piuHigh = { "Destri", "fff", "qbf", "imprinting", "site",
"Hyn", "error", "gloria", "paved", "fullmoon",
"don't remember kpop", "creedFull"};
}
}
Here's the list and I'm trying to choose 4 random items from the array
You can use Random to retrieve the random numbers from 0 to piuHigh.length - 1.
public static void main(String... args) {
String[] piuHigh = { "Destri", "fff", "qbf", "imprinting", "site",
"Hyn", "error", "gloria", "paved", "fullmoon",
"don't remember kpop", "creedFull" };
String[] fourRandomItems = getRandomItems(piuHigh, 4);
}
public static String[] getRandomItems(String[] arr, int total) {
String[] res = new String[total];
Random random = new Random();
for (int i = 0; i < res.length; i++)
res[i] = arr[random.nextInt(arr.length)];
return res;
}
If you want to chose them randomly but not repeat any, then this would be one way to do it. This avoids shuffling the entire list which isn't necessary for small sample sizes. So it only does as much of a shuffle as required to ensure you don't get repeats. This does alter the list order but does not modify the contents.
String[] piuHigh = { "Destri", "fff", "qbf", "imprinting", "site",
"Hyn", "error", "gloria", "paved", "fullmoon",
"don't remember kpop", "creedFull"};
String[] items = getItems(6, piuHigh);
for (String s : items) {
System.out.println(s);
}
prints something like
paved
Destri
error
fff
creedFull
don't remember kpop
first check to ensure there are enough items.
then select one item at random.
save it for return
then swap that with the one at the end of the given list
last is then updated to avoid re-choosing the item just chosen.
public static String[] getItems(int amount, String[] source) {
if (amount > source.length) {
throw new IllegalArgumentException("Insufficient items");
}
String[] selection = new String[amount];
Random r = new Random();
int last = source.length;
for (int i = 0; i < amount; i++) {
int select = r.nextInt(last);
String item = source[select];
selection[i] = item;
source[select] = source[--last];
source[last] = item;
}
return selection;
}
Related
I've started learning java some time ago. I'm reading through the Java Foundations book and doing exercises from the book to practice.
Just come across this one "Modify the java program so that it works for the numbers in the range between -25 and 25." and I wonder if you have any different solutions to it or is it really that simple? :)
Here's the original code:
public class BasicArray
{
public static void main(String[] args)
{
final int LIMIT = 15;
final int MULTIPLE = 10;
int[] list = new int[LIMIT];
// Initialize the array values
for(int index = 0; index < LIMIT; index++)
list[index] = index * MULTIPLE;
list[5] = 999; // change one array value
// Print the array values
for(int value : list)
System.out.println(value + "");
}
}
And here's my solution to it:
public class BasicArray
{
public static void main(String[] args)
{
final int LIMIT = 51;
final int MULTIPLE = 1;
int[] list = new int[LIMIT];
// Initialize the array values
for(int index = 0; index < LIMIT; index++)
list[index] = (index - 25) * MULTIPLE;
list[5] = 999; // change one array value
// Print the array values
for(int value : list)
System.out.println(value + "");
}
}
Yes, basically it's really simple exercise.
Regarding to your solution we actually don't need MULTIPLE in code.
public class BasicArray {
public static void main(String[] args) {
final int LIMIT = 51;
int[] list = new int[LIMIT];
// Initialize the array values
for(int index = 0; index < LIMIT; index++) {
list[index] = (index - 25);
}
list[5] = 999; // change one array value
// Print the array values
for(int value : list) {
System.out.println(value + "");
}
}
}
If you are ready for a bit of advanced java, you can try following:
public class BasicArray {
public static void main(String[] args) {
IntStream.rangeClosed(-25, 25)
.forEach(System.out::println);
}
}
Or this if you need to replace one value:
public class BasicArray {
public static void main(String[] args) {
IntStream.rangeClosed(-25, 25)
.forEach(i -> {
if (i == -20) { // change one array value
System.out.println(999);
} else {
System.out.println(i);
}
});
}
}
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 3 years ago.
I'm trying to print out the names of the employees and their department and location from a list of the names and id numbers and I keep getting the NullPointerException even though it prints all of the names and locations. It then stops the build and doesn't xecute the print department and print location methods.
I've tried re-doing the for loops and seeing if any one data point was the problem but it seems to happen if I do the loop for all of the Employee objects or if I just do one.
package homework5_parth_desai;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
/**
*
* #author Party Parth
*/
public class Homework5_Parth_Desai {
public static int emplIndex = -1;
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws FileNotFoundException {
File file = new File("acmeEgr.txt");
Scanner scan = new Scanner(file);
Employee[] emp = new Employee[50];
String s = "";
String t = "";
int r = 0;
while (scan.hasNextLine()) { //scans in file
emplIndex++;
emp[emplIndex] = new Employee();
if (scan.hasNextLine() == true) { //takes first line as first name, second as last naem and third as id number and tehn ccreates an object out of that
s = scan.nextLine();
}
if (scan.hasNextLine() == true) {
t = scan.nextLine();
}
if (scan.hasNextLine() == true) {
r = Integer.parseInt(scan.nextLine());
}
emp[emplIndex].Employee(s, t, r);
// TODO code application logic here
}
printAll(emp);
printDepartment("IT", emp);
printLocation("Auburn Hills", emp);
}
static void printAll(Employee[] ppl) {
for (int i = 0; i < ppl.length; i++) {
System.out.println(ppl[i].toString());
}
}
static void printDepartment(String title, Employee[] ppl) {
for (int i = 0; i < ppl.length; i++) {
if (title.equals(ppl[i].getDept())) {
System.out.println(ppl[i].getName() + " is in " + ppl[i].getLocation());
}
}
}
static void printLocation(String loc, Employee[] ppl) {
for (int i = 0; i < ppl.length; i++) {
if (loc.equals(ppl[i].getLocation())) {
System.out.println(ppl[i].getName() + " is in " + ppl[i].getDept());
}
}
}
}
Small exert of the .txt file:
Alexander
Seiber
10010
Zehua
Showalter
20010
Cassidy
Woodle
20030
Randall
Shaukat
10030
Pam
Korda
10020
Justin
Polito
20030
public static int emplIndex = -1;
Why is the index maintained as a static field? Don't do that.
Employee[] emp = new Employee[50];
The employee array has a fixed size of 50 elements, however
while (scan.hasNextLine()) {
this loop is based on the lines of the acmeEgr.txt file, which might be more than 50.
In that case, you'll get an ArrayOutOfBoundException first
emp[emplIndex] = new Employee();
or a NullPointerException after
emp[emplIndex].Employee(s, t, r);
Instead, if the lines are less then 50, this
for (int i = 0; i < ppl.length; i++) {
System.out.println(ppl[i].toString());
}
will still loop all the 50 elements, because
ppl.length = 50
Thus, this line
ppl[i].toString()
will throw a NullPointerException.
This is what happens if the elements are, for example, 40
System.out.println(ppl[0].toString());
System.out.println(ppl[1].toString());
System.out.println(ppl[2].toString());
System.out.println(ppl[3].toString());
...
System.out.println(ppl[40].toString()); // ppl[40] is null, NullPointerException!
ArrayList is a much easier array type to deal with. Try using it instead of a normal array, because then you don't have to deal with indexes.
I have a method that will take a List. If the List contains both "item1" and "item2", it should remove one of the
two, but I need to do it random (i.e., half the time removing "item1" and half the time removing "item2"). Otherwise it should leave the List unchanged. If you pass in null, the method should do nothing.
I have a method:
public static void removeItem(List<String> items) {
if (items.contains("item1") &&
items.contains("item2"))
{
Random random = new Random();
int randomIndex = random.nextInt(items.size());
items.remove(randomIndex);
} else if (items.isEmpty()) {
} else {
}
}
I am not sure how to make it remove half of the time. Any help appriciated
Shuffling the list can do the trick.
Though there is no guarantee of half the time clause.
You can have any number of items in the list.
May not be a optimal solution, but I can propose this:
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("item2");
list.add("item3");
list.add("item1");
list.add("item4");
System.out.println("Before : " + list);
removeItem(list);
System.out.println("After : " + list);
}
public static void removeItem(List<String> items) {
if (items == null) {
// Handle the null list
System.out.println("List is null");
} else if (items.contains("item1") && items.contains("item2")) {
//Shuffle the list, randomize the items and then remove `item1` or `item2` which ever appears earliest.
Collections.shuffle(items);
// Modern approach
items.stream().filter(i->i.equals("item1") || i.equals("item2")).findAny().ifPresent(i->items.remove(i));
/*
int removeIndex = 0;
for (int i = 0; i < items.size(); i++) {
if (items.get(i).equals("item1") || items.get(i).equals("item2")) {
removeIndex = i;
break;
}
}
items.remove(removeIndex);
*/
} else if (items.isEmpty()) {
} else {
}
This checkList method takes in a list, checks if both items are in the list, and removes one of them randomly if they both exist. Does nothing if the list is null.
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("item1");
list.add("item2");
list = checkList(list);
}
private static List<String> checkList(List<String> list){
//skip if null
if(list == null){
return list;
}
//find index of items
int index1 = list.indexOf("item1");
int index2 = list.indexOf("item2");
//if one item doesn't exist in list, its index will be -1
if(index1 >= 0 && index2 >= 0){
//get random number between 1 and 2
Random random = new Random();
int randomNumber = random.nextInt(2) + 1;
if(randomNumber == 1){
//remove item1
list.remove(index1);
}else{
//remove item2
list.remove(index2);
}
}
return list;
}
You can't guarantee one element is removed "half of the time" over the other. What you can do, however, is generate a random number of 0 or 1 and remove one of the elements based on that. This will essentially simulate what you want.
public static void removeItem(List<String> items) {
if (items == null || items.isEmpty()) {
return;
}
if (!items.contains("item1") || !items.contains("item2")) {
return;
}
int randomNumber = ThreadLocalRandom.current().nextInt(0, 2);
if (randomNumber == 0) {
items.remove("item1");
} else {
items.remove("item2");
}
}
If you mean, randomly remove any item then u can shuffle the items as per the ans of #prashantzombade and if you mean to count the time you are deleting item 1 and item 2 randomly then you can implement the logic of odd even Ni. With static variable.
make 2 static variables
get the count of static variables
implement the logic for half of the time(ex. Avg 50%)
get random no
if no. Is even then remove item 2 else item 1
increase the static variable for even no by 1 if random number is even else variable 2
If you want to implement the following process then comment on ans I will upload the code example.
Here I am checking exact count of deletion item 1 and item 2(exact half of the time)
import java.util.Random;
import java.util.*;
class hello2
{
static int evn=0;
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("item1");
list.add("item2");
int randomNumber=0;
//list = checkList(list);
//skip if null
if(list!=null){
//find index of items
int index1 = list.indexOf("item1");
int index2 = list.indexOf("item2");
//if one item doesn't exist in list, its index will be -1
if(index1 >= 0 && index2 >= 0){
//get random number between 1 and 2
Random random = new Random();
randomNumber = random.nextInt(2) + 1;
if((randomNumber %2)== 0){
//remove item1
if(evn==1) //if last time item 2 deleted
{
list.remove(index2);
//System.out.println(list+" Static var="+evn+" Random no: "+randomNumber%2);
evn=0;
}
//else{System.out.println(list+" Static var="+evn+" Random no: "+randomNumber%2);}
}else{
//remove item2
if(evn==0) //if last time item 1 deleted
{
list.remove(index1);
//System.out.println(list+" Static var="+evn+" Random no: "+randomNumber%2);
evn=1;
}
//else{System.out.println(list+" Static var="+evn+" Random no: "+randomNumber%2);}
}
}
System.out.println(list);
}
}
}
I am trying to generate unique random number using the below function. Whenerver I run my code in a loop of 1000, it generates duplicate number also.
Code
private static String randomize() {
int count = 10;
List<Integer> digits = createList(count);
Collections.shuffle(digits); // this re-arranges the elements in the list
return listToString(digits);
}
private static <T> String listToString(List<T> list) {
StringBuilder result = new StringBuilder();
for (T object : list) {
result.append(object);
}
return result.toString();
}
private static List<Integer> createList(int size) {
List<Integer> result = new ArrayList<Integer>(size);
for (int i = 0; i < size; i++) {
result.add(i);
}
return result;
}
public static void main(String[] args) {
for (int i = 0; i < 1000; i++) {
String strName = randomize();
System.out.println(strName);
}
I searched a lot in google and tried ThreadLocal also, it did not help me. Any help or guide on this will be really helpful. My idea is to generate 10 digit non-repeating random number within a loop.
You're not really generating random numbers, are you? You're generating random permutations of the 10 unique digits [0..9]. (e.g. "0123456789", "9834105672", etc.) Since there are only 3268800 (10!) unique permutations, you have a decent chance of hitting a duplicate with 1000 tries.
(I haven't worked out the math, but since 1000^2 is within an order of magnitude of 10!, my intuition tells me there's at least a 10% chance of a duplicate in any given set. Google "birthday paradox" for details.)
What you want to do, and what #Andrei is trying to explain, is to check/store the result every time you call randomize() to make sure you don't have duplicates. Roughly:
public static void main(String[] args) {
Set<String> results = new HashSet<>(1000);
while (results.size() < 1000) {
String strName = randomize();
if (!results.contains(strName)) {
System.out.println(strName);
results.add(strName);
}
}
}
Unless of course you actually want a set of random numbers:
public static void main(String[] args) {
Set<Long> results = new HashSet<>(1000);
while (results.size() < 1000) {
// Random number on [1E9..1E10]
long random = (long) (Random.nextDouble() * 900000000L) + 100000000L;
if (!results.contains(random)) {
System.out.println(random);
results.add(random);
}
}
}
I want to make a function that pick a randomly number in array and avoid to pick the same number in next time.
Here is my code (it work in sometime and mostly inf-loop)
please help me, Thank you.
private static int pick(int[] x) {
int upperbound = x[x.length-1];
int lowerbound = x[0];
int count=0;
int ranvalue;
int ranindex;
Random rand = new Random();
do{
ranindex = rand.nextInt(upperbound-lowerbound) + lowerbound;
count++;
}while(x[ranindex]==-1||count!=x.length-1);
ranvalue=x[ranindex];
x[ranindex]=-1;
return ranvalue;
}
If your array has size n, then you can get at most n different indexes. I advise the following :
Create an array with numbers from 0 to n-1.
Shuffle it.
At each step, take the next element from this array and use it as an offset for your source array.
You should also wrap this logic into a class like this :
public class Picker {
private int[] source;
private List<Integer> offsets;
private int currentIndex = 0;
public Picker(int[] source) {
this.source = source;
Integer[] indexes = new Integer[source.length];
for(int i=0;i<source.length;i++) {
indexes[i] = i;
}
this.offsets = Arrays.asList(indexes);
Collections.shuffle(this.offsets);
}
public Integer next() {
return source[offsets.get(currentIndex++)];
}
}
Example :
public static void main(String[] args) {
int[] source = {8,3,5,9};
Picker picker = new Picker(source);
for(int i = 0; i<4;i++) {
System.out.println(picker.next());
}
}
Output :
5
3
8
9
EDIT : Or even simpler :
Integer[] source = {8,3,5,9};
//Copy the source and shuffle it
List<Integer> dest = Arrays.asList(source);
Collections.shuffle(dest);
//Then display
for (int i = 0;i<source.length;i++) {
System.out.println(dest.get(i));
}