Java: How to have one array reference the start of another? - java

Im trying to make a fun application that will take a sound file and modify it, and create a new sound file.
One of the things I am trying to do is make the sound file twice as long. So I essentially make a new array that goes {2,2,3,3,7,7,8,8} instead of the original {2,3,7,8}. I am using doubles, this is simply an example
I want the original array (samples) to now reference the start of the array I just created (temp) so when the file saves it now save the temp array.
I can increase or decrease the volume of the music file no problem, and save it as such. I omitted that part of the code as it is not pertinent here.
If anyone is kind enough to help me, I also want to know the why behind it
public class Sound {
double[] samples;
//So we only have to declare it once. Reference to an array
public Sound() {
//This constructor should initialize the samples array to be empty
samples = new double[0];
//Initialize an array with nothing because we will be using that to reference the
//location of other arrays
}
public void wavRead(String fileName) {
samples = WavIO.read(fileName);
//Samples was an adress of an array we set to 0. Then we used WavIO to create an aray of doubles, now
//we tell samples to reference this new address over here. Samples has the addsss of the new array
}
public void wavSave(String fileName) {
WavIO.write(fileName, samples);
}
public void lengthen() {
double[] temp = new double[(samples.length *2)];
int t = 0;
for(int i = 0; i < samples.length; i++) {
//Set a variable to increase the temp array by
temp[t] = samples[i];
//Have position 0 of temp = position 0 of soundRaw
t++;
//Increase the position in the temp array by one
temp[t] = samples[i];
//Have position 1 of temp array = position 0 of soundRaw
}
samples[0] = temp;
//Here is where I try and have the samples array reference the start of another array. I tried multiple things, this is simply the last effort I tried
}
And here is the application I am using to test the code
public class App {
public static void main(String[] args) {
Sound s = new Sound();
//We are now calling the other code
s.wavRead("bye8");
//If you want to mess with your own .wav file, replace this name
s.lengthen();
s.wavSave("bye8New");
}
}

Replacing this code line
samples[0] = temp;
with just
samples = temp;
will suffice! :)

Use a DoubleBuffer, it is much easier to do what you want to achieve.
To create a new DoubleBuffer which is... Double... The size and duplicates, you'll then do:
// Important!
origBuf.rewind();
final DoubleBuffer newBuf = DoubleBuffer.allocate(origBuf.remaining() * 2);
double value;
while (origBuf.hasRemaining()) {
value = origBuf.get();
newBuf.put(value).put(value);
}
Then newBuf.array() will return the double[] array "with duplicates".
Also note that a DoubleBuffer, like any XBuffer, allows you to set endianness.

Just use samples=temp; instead of samples[0] = temp;!

Related

understand Array Object, and what I want to do is call my array in every class I have

I'm trying to understand Array Object, and what I want to do is call my array in every class I have.
this is my code:
projectProva.java
public class ProjecteProva {
Scanner sc = new Scanner(System.in);
private final int maxContador = 4;
private final DadeArr LlistaUsuari[] = new DadeArr[maxContador];
int ContadorActual;
}
DadeArr.java
public class DadeArr {
private String nomUsuari;
private String cognomUsuari;
public DadeArr(String nU, String nC){
nomUsuari = nU;
cognomUsuari = nC;
}
Right now I'm working in projectProva.java , I have some method that saves into array a data input with scanner.
Here is an example of one of my method:
public int inserir(int aContadorActual){
ContadorActual = 1;
for (int i=1;i<=ContadorActual;++i){
System.out.println("Introdueix el nom del usuari: ");
String nU = sc.nextLine();
//sd.setNomUsuari(Name);
System.out.println("Introdueix el teu cognom : ");
String nI = sc.nextLine();
LlistaUsuari[ContadorActual] = new DadeArr(nU,nI);
System.out.println("El teu usuari s'ha creat satisfactoriament");
}
ContadorActual++;
return ContadorActual;
}
This method asks user his name and surname and saves it in array LlistaUsuari.
Then, I want to use this array(with the data in) in another .java file from the same package, but i don't know how to properly call the array.
I just started to learn this type of array, and i want to understand it.
After solving this , im looking forward to take all array info and send it to a data base or text file.
If I can't proceed with it i will switch to Array 2D.
Plus, I'm wondering if this type of Array ( array object ) is very usefull or not.
Thanks.
I also made this question at https://www.reddit.com/r/javahelp/comments/dsyu4b/array_object/?
You have multiple gotchas in your code.
1. you should always iterate an array from index 0 (unless you have special needs or you are programming in a language like Python where arrays start from 0)
2. You should set the condition in the loop to be less than the exact length of the array. So in your case it will be i < LlistaUsuari.length. You are getting a null because you are only filling up index #1 of the array.
All you need is a public getter method for the array that you want to access.
Something like:
public DadeArr[] getLlistaUsuari() {
return this.LlistaUsuari;
}
And that should do it.
In other classes, create an instance of ProjecteProva (lets's call it pPI) and to get the array there, simply do pPI.getLlistaUsuari() and you'll have it,

Removing null values from array and getting it from the method in Java

I'm trying to remove null values from an array, and returning them to do some other stuff with the new values. However, I'm confused about how to get the updated array.
This is the null removal code.
String[] removeNull(String[] nullArray) {
int nullCounter = 0;
//checking if any is null
for(int i = 0; i < nullArray.length; i++) {
if(nullArray[i]==null) {
nullCounter++;
}
}
String[] noNulls = new String[nullArray.length-nullCounter];
if(nullCounter>0) {
//make a non null array
for(int i = 0, j = 0; i <noNulls.length; i++) {
if(nullArray[i]!=null) {
noNulls[j] = nullArray[i];
j++;
}
}
}
return noNulls;
}
I'm pretty sure that is already correct (Please correct me if I'm wrong). Then, I called it inside a constructor.
public theBoundary(String[] bounds){
removeNull(bounds);
}
After I called removeNull(bounds), will the value of the new array be stored in the array bounds? Or will it be stored in the array noNull? I can't seem to find where the new values are stored.
Thank you, and please tell me if there are mistakes. I've been going around this for half an hour now.
Note: If possible, please don't give me answers that include importing something else. Vanilla Java would be preferred.
removeNull() returns the array noNulls, created inside the method. Currently, in theBoundary(), you simply call removeNull(bounds), but do not assign it to a variable. The newly created null-free array is created, not assigned, and immediately garbage collected.
If you wish to do something with your non-null-containing array (which I assume you do), do this:
public theBoundary(String[] bounds) {
String[] withoutNulls = removeNull(bounds);
doSomething(withoutNulls); // whatever you need here
}
Note, unless you really have to use an array, consider using a List or even a Stream.
List example:
List<String> list = ... // from somewhere else
list.removeIf(s -> s == null);
doSomething(list);
Stream example:
Stream<String> stream = ... //from somewhere else
stream.filter(s -> s != null);
doSomething(stream);
EDIT
Even if you do really need arrays, the following will also work:
String[] noNulls = (String[]) Arrays.stream(inputArray).filter(Objects::nonNull).toArray();
I don't think there is any need to iterate the array twice!
You can instead use a stream on array and filter the indexes without that are NOT NULL.
Also, you can do this without needing to create the removeNull method, and do this directly in your theBoundary method.
Here is how your code will look like:
String[] arrayWithoutNull = Arrays.stream(bounds).filter(Objects::nonNull).toArray(String[]::new)
I hope this solves your problem.
Do you mean this?
public theBoundary(String[] bounds){
String[] cleanedBounds = removeNull(bounds);
}
You are not doing it inplace so you need to assign it back to a new array

Sorting a randomized array in Java

I am trying to make an app for sorting a randomized array
I made some code and I can not see what is wrong with it that it returns wrong values
Notes: I am trying to learn programming. So don't suggest whole different ways of solving the problem. I just want to see what is wrong with this code so I can get better.
What RandomArrayCreator.create() returns is just an array of numbers in randomized order.
public class ArraySorter
{
public static void main(String[] args)
{
int[] siyahi = RandomArrayCreator.create();
int[] siralanmish = new int[siyahi.length];
for (int i=0;i<siyahi.length;i++)
{
for (int j=0;j<siyahi.length;j++)
{
for (int k=j+1;k<siyahi.length;k++)
{
if (siyahi[k]<siyahi[j]) j=k;
}
siralanmish[i]=siyahi[j];
siyahi[j]=siyahi.length+1;
}
System.out.println(siralanmish[i]);
}
}
}
I know you did not want suggestions but I'm going to offer one anyway.
Hopefully this will help guide you along the way, but still allow you to come up with your own solution.
Sort smallest to biggest.
did I have swap an element?
while I swapped an element
assume I did not swap an element
for element i in the array
is i > i+1?
if yes
swap the elements
I did swap an element
else
do nothing
Given that you mentioned you wanted to learn how to improve your current program, here are minimalist changes that will have your code produce a sorted array.
A few notes on the changes:
1.
if (siyahi[k]<siyahi[j]) j=k;
This I assume is for trying to swap the values at each indexes. Instead you are assigning the value of k to j which will cause problems with the entire for loop. I replaced this with the following:
if (siyahi[k]<siyahi[j])
{
int temp = siyahi[j];
siyahi[j] = siyahi[k];
siyahi[k] = temp;
}
This creates a temporary variable to store one of the values so that you can swap the value at each index without losing one of your values.
2.
siralanmish[i]=siyahi[j];
This was replaced with:
siralanmish[j]=siyahi[j];
This allows you to directly copy the values from the same index from the source array to the target array.
3.
siyahi[j]=siyahi.length+1;
This code will just fill up your array with the value of length+1 for your original array and you will lose your other values.
Your code with the fixes are below:
public class ArraySorter
{
public static void main(String[] args)
{
int[] siyahi = RandomArrayCreator.create();
int[] siralanmish = new int[siyahi.length];
for (int i=0;i<siyahi.length;i++)
{
for (int j=0;j<siyahi.length;j++)
{
for (int k=j+1;k<siyahi.length;k++)
{
if (siyahi[k]<siyahi[j])
{
int temp = siyahi[j];
siyahi[j] = siyahi[k];
siyahi[k] = temp;
}
}
siralanmish[j]=siyahi[j];
}
System.out.println(siralanmish[i]);
}
}

Copying an object using a constructor, Java

So lets say I want to make a deep copy of an object, but using its contsructor. So I have:
public class PositionList {
private Position[] data = new Position[0];
private int size = 0;
public PositionList(PositionList other, boolean deepCopy) {
if (deepCopy==true){
size=other.getSize();
for (int i=0;i<data.length;i++)
data[i]=other.data[i];
}
else {
data=other.data;
size = other.size;
And so say I have this being called:
PositionList list = new PositionList();
PositionList acopy = new PositionList(list, true);
What I am doing, however, is incorrect, and Im not sure why..
The problem lies in your deep copy logic:
size=other.getSize();
for (int i=0;i<data.length;i++)
data[i]=other.data[i];
You are setting the size field (which is redundant with the data array) but are not assigning a new array to the data field, which is presumably the whole point of your "deep" copy. You should initialize data to the other's size (or other.data.length):
data = new Position[other.data.length];
for (int i=0;i<data.length;i++)
data[i]=other.data[i];
(And get rid of size all together)

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