Java Changing variable from another class and the depending values - java

I have a problem with my class variables, as always ^^
So I'm constructing a class named Prng, with variables
private int randListSize = 10;
private byte randList[] = new byte[randListSize];
private byte[] seed = new byte[]{ 34, -70, -4, 117, 98 };
the getters/setters associated
and the method
public void prng() {
SecureRandom random;
try {
random = SecureRandom.getInstance("SHA1PRNG");
random.setSeed(seed);
random.nextBytes(randList);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
in another class named Test.java, I want to :
1) set randListSize to /number of random bytes I want
2) have the randList of this size, and not from original 10 size
whenever I try, my randList is always of size 10. Can you help me please ?
in my class Test I've written :
Prng prng = new Prng();
System.out.println(prng.getRandListSize() + " " + prng.getRandList().length);
prng.setRandListSize(11);
System.out.println(prng.getRandListSize()+ " " + prng.getRandList().length);
which returns me "10 10 ; 11 10" and I want "11 11" at the end.
EDIT : here's my getters/setters :
public int getRandListSize() {
return randListSize;
}
public void setRandListSize(int randListSize) {
this.randListSize = randListSize;
}
public byte[] getSeed() {
return seed;
}
public void setSeed(byte[] seed) {
this.seed = seed;
}
public byte[] getRandList() {
return randList;
}
public void setRandList(byte[] randList) {
this.randList = randList;
}

First, randListSize, in my opinion, is a useless field, as that property can be retrieved directly from the array, and as the operation isn't expensive the value doesn't need to be cached. Thus, you really don't need getters/setters for that field either. I see you're using it as an initial size variable, but in that case I think it'd be better for it to be a parameter for a constructor/factory method instead, as it really doesn't need to be used anywhere else.
Second, setRandListSize() doesn't actually change randList's size, as arrays, once created, cannot be structurally modified (i.e. you can't make arrays longer/shorter after creating them). You're just changing an unrelated variable, which leads to some confusion once randListSize stops matching randList.length. This is the reason you're seeing 11 10 instead of 11 11 -- randListSize is only used at the moment of array creation, and later changes to randListSize don't affect the array.
In order to get the result you want, you're going to have to allocate an entirely new array and set randList to point to it instead of your old one, which you can do using your setRandList() method. Alternatively, you can write a method, perhaps called createNewRandList(int newLength), to do all the work at once.

Your setRandListSize method will need to recreate the randList array. If you need to keep the data in it, your method should copy whatever data can fit into the new array.
public void setRandListSize(int randListSize) {
this.randListSize = randListSize;
this.randList = new byte[randListSize];
}

Related

Can this be a correct way to set an inclusive scale?

Sorry this is my first post it might be vague and it might be not. Hopefully I can supply enough information. So:
I want to take a whole number from the user I know (int) of course but I want it to be from the scale 3 to 5 inclusive.
Am I right in doing the following:
public Number(int enteranumber)
{
enteranumber = 3;
}
does this mean that if the user tries to enter a number less than three then the field will automatically set to 3. And when the user enters a greater than 3 then the value of enteranumber will change to whatever the user put.
I think this needs an if statement, but I don't think it's correct to have it in a constructor. That's what I have been told anyway
Thank you very much for the help.
The current code snippet you have provided will overwrite the value of enteranumber to be 3 when a new Number() object is instantiated. No matter what is passed in that parameter, i.e. new MyNumber(69), the constructor will overwrite the passed parameter immediately, that 69 to be 3 basically.
Being done inside the constructor is fine, if that is what you are wanting to do. Do you want the logic to run when you instantiate the object, or at a different time? If the former, then in the constructor is just fine. Here would be how you would do that
/**
* Primary class
*/
class MyMainClass
{
public static void main(String[] args)
{
MyNumber number = new MyNumber(69);
System.out.print(number.getEnterANumber()); // Output will be 5 in this scenario
}
}
/**
* Number POJO
*/
class MyNumber
{
private int enteranumber_;
public Number(int enteranumber)
{
// Sets the value
enteranumber_ = enteranumber;
// Checks if the value is on the wrong side of 3
if(enteranumber_ < 3)
{
// If it is, then sets the number to 3
setEnterANumber(3);
{
// If you want the number to definitely be 3 - 5 inclusive
else if(enteranumber_ > 5)
{
setEnterANumber(5);
}
}
// Modifier
private static void setEnterANumber(int enteranumber)
{
enteranumber_ = enteranumber;
{
// Accessor
public int getEnterANumber()
{
return enteranumber_;
}
}
The only time this if else block will change the value is if the passed value is 0, 1, 2, 6, 7, 8, ...

Lexicographic quicksort algorithm

My professor gave me a code for the methods to be used in sorting an array of names lexicographically, but I have no idea how what to write inside the main class to show that the program works. I am very new to java, so please if you know how to do this could you write it as simple as possible for me to understand it. Thanks in advance.
This is are the classes
public class quicksort_class {
int[] array1 = new int[11];
public quicksort_class(int[] w)
{
array1 = w;
}
private static void sort(String[] string, int leftlimit, int rightlimit) {
if (rightlimit > leftlimit)
{
int midpoint = partitionstep(string, leftlimit, rightlimit);
sort(string, leftlimit, midpoint - 1);
sort(string, midpoint, rightlimit);
}
}
public static int partitionstep(String[] string, int leftlimit, int rightlimit)
{
String midpoint = string[rightlimit];
int lpointer = leftlimit;
int rpointer = rightlimit;
String temp = "";
while(string[lpointer].compareTo(midpoint) <= 0)
{
lpointer = lpointer ++;
}
while(string[rpointer].compareTo(midpoint) > 0)
{
rpointer = rpointer --;
}
if(lpointer > rpointer)
{
temp = string[lpointer];
string[lpointer] = string[rightlimit];
string[rpointer] = temp;
System.out.println(string);
}
while(lpointer < rpointer)
{
temp = string[lpointer];
string[lpointer] = string[rightlimit];
string[rightlimit] = temp;
}
return lpointer;
}
}
This is the main class (as you can see I have no idea what to write)
package quicksort;
public class Quicksort {
public static void main(String[] args) {
}
}
Write something that sets up an array of strings and calls sort against it, then prints out the results or checks them against a known good result.
Ideally, write something which does this repeatedly, with particular emphasis on checking unusual combinations (already sorted or sorted in reverse, null in the array, same value appearing several times or all values being identical...)
If you want to go beyond that, you need to dig into the code to understand its edge cases and specifically test those, and/or do a "code coverage" analysis (there are tools to help with that) to make sure all parts of the code have been exercised.
Assume the algorithm of sort method is correct:
1. If the main method is within the body of quicksort_class, you can directly call the sort method as sort(arrayToBeSorted, 0 , arrayToBeSorted.length-1). And the arrayToBeSorted should ordered lexicographically after your call. You can check that to confirm.
2. If the main method is in other class, as your main method currently, you need to at least change the private prefix of sort method to public, and call quicksort_class.sort(arrayToBeSorted, 0 , arrayToBeSorted.length-1).
Some tips:
1. Private prefix of method definition means this method can only be called inside current class body.
2. Static prefix of method definition means you should call this method via class name directly, instead of via a instance of class.
By the way, can you provide what the array1 attribute stands for? I don't get why it's there.

Library for serializing java objects to fixed-width byte arrays

I would like to store a very simple pojo object in binary format:
public class SampleDataClass {
private long field1;
private long field2;
private long field3;
}
To do this, I have written a simple serialize/deserialize pair of methods:
public class SampleDataClass {
// ... Fields as above
public static void deserialize(ByteBuffer buffer, SampleDataClass into) {
into.field1 = buffer.getLong();
into.field2 = buffer.getLong();
into.field3 = buffer.getLong();
}
public static void serialize(ByteBuffer buffer, SampleDataClass from) {
buffer.putLong(from.field1);
buffer.putLong(from.field2);
buffer.putLong(from.field3);
}
}
Simple and efficient, and most importantly the size of the objects in binary format is fixed. I know the size of each record serialized will be 3 x long, i.e. 3 x 8bytes = 24 bytes.
This is crucial, as I will be recording these sequentially and I need to be able to find them by index later on, i.e. "Find me the 127th record".
This is working fine for me, but I hate the boilerplate - and the fact that at some point I'm going to make a mistake and end up write a load of data that can't be read-back because there's an inconsistency between my serialize / deserialize method.
Is there a library that generate something like this for me?
Ideally I'm looking for something like protobuf, with a fixed-length encoding scheme. Later-on, I'd like to encode strings too. These will also have a fixed length. If a string exceeds the length it's truncated to n bytes. If a string is too short, I'll null-terminate it (or similar).
Finally, protobuf supports different versions of the protocol. It is inevitable I'll need to do that eventually.
I was hoping someone had a suggestion, before I start rolling-my-own
Make your class inherit the java.io.Serializable interface. Then you can use java.io.ObjectOutputStream and java.io.ObjectInputStream to serialize / deserialize objects to / from streams. The write and read methods take byte arrays as arguments.
To make it fixed length, standardize the size of the byte[] arrays used.
The most difficult part here is capping your strings or collections. You can do this with Kryo for Strings by overriding default serializers. Placing strings into a custom buffer class (i.e. FixedSerializableBuffer) which stores or is annotated with a length to cut also makes sense.
public class KryoDemo {
static class Foo{
String s;
long v;
Foo() {
}
Foo(String s, long v) {
this.s = s;
this.v = v;
}
#Override
public String toString() {
final StringBuilder sb = new StringBuilder("Foo{");
sb.append("s='").append(s).append('\'');
sb.append(", v=").append(v);
sb.append('}');
return sb.toString();
}
}
public static void main(String[] args) {
Kryo kryo = new Kryo();
Foo foo = new Foo("test string", 1);
kryo.register(String.class, new Serializer<String>() {
{
setImmutable(true);
setAcceptsNull(true);
}
public void write(Kryo kryo, Output output, String s) {
if (s.length() > 4) {
s = s.substring(0, 4);
}
output.writeString(s);
}
public String read(Kryo kryo, Input input, Class<String> type) {
return input.readString();
}
});
// serialization part, data is binary inside this output
ByteBufferOutput output = new ByteBufferOutput(100);
kryo.writeObject(output, foo);
System.out.println("before: " + foo);
System.out.println("after: " + kryo.readObject(new Input(output.toBytes()), Foo.class));
}
}
This prints:
before: Foo{s='test string', v=1}
after: Foo{s='test', v=1}
If the only additional requirement over standard serialization is efficient random access to the n-th entry, there are alternatives to fixed-size entries, and that you will be storing variable length entries (such as strings) makes me think that these alternatives deserve consideration.
One such alternative is to have a "directory" with fixed length entries, each of which points to the variable length content. Random access to an entry is then implemented by reading the corresponding pointer from the directory (which can be done with random access, as the directory entries are fixed size), and then reading the block it points to. This approach has the disadvantage that an additional I/O access is required to access the data, but permits a more compact representation of the data, as you don't have to pad variable length content, which in turn speeds up sequential reading. Of course, neither the problem nor the above solution is novel - file systems have been around for a long time ...

Generate unique random number on each call

In a interview I was asked to wrtie a method which will generate unique 5 digit random number everytime when it is called.For ex: if I call the method and get 22222 then in next call i should not get 22222.
I wrote a code as below:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
public class RandomNumberGen {
private static ArrayList arr=new ArrayList();
private static int k=-1;
public RandomNumberGen(){
for (int i=10000;i<99999;i++){
arr.add(i);
}
Collections.shuffle(arr);
}
public static void main(String[] args) {
for(int m=0;m<10;m++){
try {
System.out.println(new RandomNumberGen().randomNumbermethod());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public Integer randomNumbermethod() throws Exception{
k++;
if(k>=arr.size()){
throw new Exception("No more number available");
}else return (Integer) arr.get(k);
}
}
Answer got accepted but I was asked to avoid memory wastage now.
My question is here as you can see I am using only 10 numbers.So rest of the space occupied by arraylist is a memory-wastage.Is there a way I can achieve same thing without using extra memory.
What I mean is there someway using which unique number can be generated on each call so that this much memory do not get wasted.
private static int number = 10000;
public int getNextUniqueRandomNumber() {
return number++;
}
Implications:
In order to not to return the same value twice, you need to track which numbers you've already generated. This can be very memory consuming.
You eventually run out of numbers. Instead of keeping on searching for an unused random number, you can track how many numbers you've returned (or how many are still available) and recognize if you ran out of numbers.
The generated numbers could be tracked in a collection (Set). This means having an overhead of 32bit per number (when tracking available or generated numbers) plus the collection overhead. Another possibility is to use a boolean-array and mark which slots have been used. Again, this is an overhead, as booleans usually are stored as 32bit value.
But there's a cheaper way to store booleans: as packed bits in an integer. That's what java.util.BitSet does, so each boolean will occupy one bit.
Solution with BitSet and tracking how many numbers are available:
public class RandomNumbers {
private final Random random = new Random();
private final BitSet used = new BitSet();
private final int min = 10000;
private final int max = 99999;
private final int numbersAvailable = max - min + 1;
public static void main (String[] args) {
RandomNumbers randomNumbers = new RandomNumbers();
for (int i = 0; i < 100; i++) {
System.out.println(randomNumbers.nextRandom());
}
}
public int nextRandom () throws NoSuchElementException {
while (numbersAvailable > 0) {
int rnd = min + random.nextInt(max - min + 1);
if (!used.get(rnd)) {
used.set(rnd);
numbersAvailable--;
return rnd;
}
}
throw new NoSuchElementException();
}
}
Just
(int)(Math.random()*89999)+10000
After edit: (just not understood before edit) - you can put generated number in HashSet and after random just check if set contains new number (it will go very slow if you use it many times, but I think this is a good solution if you don't need a lot of numbers.
From my comment: After exceding about 50% of numbers I would create a collection of remaining numbers to pick, same as yours, but you should document in class, that it can freeze for a moment after 50% results usage and give ability to set this factor to client.
Maybe ther is a better way, depending of "how much randomness" must be in generated numbers (for example mathematical approach to sequence generator)
Seems pretty straightforward. A much simpler solution with less memory usage is to just create a set that will hold all the numbers you want like this:
Random random = new Random();
Set<Integer> randomNumbers = new HashSet<Integer>(10);
while(randomNumbers.size() < 10)
randomNumbers.add( new Integer(random.nextInt(89999) + 10000) );
And to view them all:
for(Integer randomNumber : randomNumbers){
System.out.println(randomNumber);
}
This will guarantee uniqueness to the properties of a set and greatly improve your memory usage.
Your method would indeed be ideal to create a large number of unique values, however if you are only creating a small number of unique values it can be more efficient to simply keep track of the used values to garantee uniqueness
import java.util.Collection;
import java.util.HashSet;
import java.util.Random;
public class UniqueRandom {
static Random rnd=new Random();
public static void main(String args[]){
Collection<Integer> alreadyChosen = new HashSet<Integer>();
for(int i=0;i<10;i++){
System.out.println(getNextUniqueRandom (alreadyChosen));
}
}
public static int getNextUniqueRandom(Collection<Integer> alreadyChosen){
if (alreadyChosen.size()==90000){ //hardcoded 5 figure numbers, consider making a variable
throw new RuntimeException("All 5 figure IDs used");
}
boolean unique=false;
int value=0;
while(unique==false){
value=rnd.nextInt(90000)+10000;
unique=!alreadyChosen.contains(value);
}
alreadyChosen.add(value);
return value;
}
}
This method is highly efficient when only a small proportion of the available range is required but becomes slower and slower as collisions become more common. The exact implementation you should choose is highly dependant upon how many values you need to get.
Notes to consider
As already stated this will get very very slow as more values are
chosen, should be made clear to end user, or even better; change algorithm after so many calls

Returning searched results in an array in Java without ArrayList

I started down this path of implementing a simple search in an array for a hw assignment without knowing we could use ArrayList. I realized it had some bugs in it and figured I'd still try to know what my bug is before using ArrayList. I basically have a class where I can add, remove, or search from an array.
public class AcmeLoanManager
{
public void addLoan(Loan h)
{
int loanId = h.getLoanId();
loanArray[loanId - 1] = h;
}
public Loan[] getAllLoans()
{
return loanArray;
}
public Loan[] findLoans(Person p)
{
//Loan[] searchedLoanArray = new Loan[10]; // create new array to hold searched values
searchedLoanArray = this.getAllLoans(); // fill new array with all values
// Looks through only valid array values, and if Person p does not match using Person.equals()
// sets that value to null.
for (int i = 0; i < searchedLoanArray.length; i++) {
if (searchedLoanArray[i] != null) {
if (!(searchedLoanArray[i].getClient().equals(p))) {
searchedLoanArray[i] = null;
}
}
}
return searchedLoanArray;
}
public void removeLoan(int loanId)
{
loanArray[loanId - 1] = null;
}
private Loan[] loanArray = new Loan[10];
private Loan[] searchedLoanArray = new Loan[10]; // separate array to hold values returned from search
}
When testing this, I thought it worked, but I think I am overwriting my member variable after I do a search. I initially thought that I could create a new Loan[] in the method and return that, but that didn't seem to work. Then I thought I could have two arrays. One that would not change, and the other just for the searched values. But I think I am not understanding something, like shallow vs deep copying???....
The return value from getAllLoans is overwriting the searchedLoanArray reference, which means that both loanArray and searchedLoanArray are pointing at the same underlying array. Try making searchedLoanArray a local variable, and then use Arrays.copyOf. If you're trying not to use standard functions for your homework, manually create a new Loan array of the same size as loanArray, and then loop and copy the values over.
your searchloanarray and loanarray point to the same array. doing this
private Loan[] searchedLoanArray = new Loan[10]
does nothing as you never use that new Loan[10]
this is the key to your problem
searchedLoanArray = this.getAllLoans()
that just points searchedLoanArray at loanArray
You could rewrite it like this:
public Loan[] findLoans(Person p)
{
Loan[] allLoans = this.getAllLoans();
System.arraycopy(allLoans, searchedLoanArray, 0, 0, allLoans.length); // fill new array with all values
// remainder of method the same
}
But as it stands, the code still has some problems:
The maximum number of loans is fixed to the size of the array. You will avoid this problem when you switch to List<Loan>.
Using the id as an index means that your ids must be carefully generated. If IDs come from a database, you may find that the list tries to allocate a huge amount of memory to size itself to match the Id. You would be better using a Map, then the size of the map is based on the number of loans, rather than their IDs.
As the number of people and loans increase, the search time will also increase. You can reduce search time to a constant (irrespective of how many People) by using a Map>, which allows quick lookup of the loans associated just with that person.
Here's a version with these changes:
class AcmeLoanManager
{
public void addLoan(Loan l)
{
Person client = l.getClient();
List<Loan> loans = clientLoans.get(l);
if (loans==null)
{
loans = new ArrayList();
clientLoans.put(client, loans);
}
loans.add(l);
allLoans.put(l.getLoanId(), l);
}
public void removeLoan(int loanId)
{
Loan l = loans.remove(loanId);
clientLoans.remove(loan);
}
public Collection<Loan> getAllLoans()
{
return loans.values();
}
public List<Loan> findLoans(Person p)
{
List<Loan> loans = clientLoans.get(p);
if (loans==null)
loans = Collections.emptyList();
return loans;
}
private Map<Integer,Loan> allLoans = new HashMap<Integer,Loan>();
private Map<Person, List<Loan>> clientLoans = new HashMap<Person,List<Loan>>();
}
I hope this helps!
What I would do is loop through the values and reassign each value to the new variable. Alternatively, you could use "deep copy" technique as described here in Javaworld: http://www.javaworld.com/javaworld/javatips/jw-javatip76.html

Categories