Why isn't it an error? - java

The following program is a recursive program to find the maximum and minimum of an array.(I think! Please tell me if it is not a valid recursive program. Though there are easier ways to find the maximum and minimum in the array, I'm doing in the recursive manner only as a part of a exercise!)
This program works correctly and produces the outputs as expected.
In the comment line where I have marked "Doubt here!", I am unable to understand why an error is not given during compilation. The return type is clearly an integer array (as specified in the method definition), but I have not assigned the returned data to any integer array, but the program still works. I was expecting an error during compilation if I did it this way, but it worked. If someone would help me figure this out, it'd be helpful! :)
import java.io.*;
class MaxMin_Recursive
{
static int i=0,max=-999,min=999;
public static void main(String[] args) throws IOException
{
BufferedReader B = new BufferedReader(new InputStreamReader(System.in));
int[] inp = new int[6];
System.out.println("Enter a maximum of 6 numbers..");
for(int i=0;i<6;i++)
inp[i] = Integer.parseInt(B.readLine());
int[] numbers_displayed = new int[2];
numbers_displayed = RecursiveMinMax(inp);
System.out.println("The maximum of all numbers is "+numbers_displayed[0]);
System.out.println("The minimum of all numbers is "+numbers_displayed[1]);
}
static int[] RecursiveMinMax(int[] inp_arr) //remember to specify that the return type is an integer array
{
int[] retArray = new int[2];
if(i<inp_arr.length)
{
if(max<inp_arr[i])
max = inp_arr[i];
if(min>inp_arr[i])
min = inp_arr[i];
i++;
RecursiveMinMax(inp_arr); //Doubt here!
}
retArray[0] = max;
retArray[1] = min;
return retArray;
}
}

The return type is clearly an integer array (as specified in the method definition), but I have not assigned the returned data to any integer array, but the program still works.
Yes, because it's simply not an error to ignore the return value of a method. Not as far as the compiler is concerned. It may well represent a bug, but it's a perfectly valid use of the language.
For example:
Console.ReadLine(); // User input ignored!
"text".Substring(10); // Result ignored!
Sometimes I wish it could be used as warning - and indeed Resharper will give warnings when it can detect that "pure" methods (those without any side-effects) are called without using the return value. In particular, call which cause problems in real life:
Methods on string such as Replace and Substring, where users assume that calling the method alters the existing string
Stream.Read, where users assume that all the data they've requested has been read, when actually they should use the return value to see how many bytes have actually been read
There are times where it's entirely appropriate to ignore the return value for a method, even when it normally isn't for that method. For example:
TValue GetValueOrDefault<TKey, TValue>(Dictionary<TKey, TValue> dictionary, TKey key)
{
TValue value;
dictionary.TryGetValue(key, out value);
return value;
}
Normally when you call TryGetValue you want to know whether the key was found or not - but in this case value will be set to default(TValue) even if the key wasn't found, so we're going to return the same thing anyway.

In Java (as in C and C++) it is perfectly legal to discard the return value of a function. The compiler is not obliged to give any diagnostic.

Related

How to find the number of times a specific element occurs in an Array list in Java

I have written a method with the aim to count the number of times a specific flavour of crisps appears in a snack machine in blueJ
public int countPacks(String flavour){
int n = 0;
int nrFlavour = 0;
while( n < packets.size()) {
if( packets.get(n).equals(flavour)){
nrFlavour++;
n++;
}
else n++;
}
return nrFlavour;
}
I have an Arraylist 'packets' which holds PackOfCrisps objects which have a specific flavour. However when I have added say three packets of "salt" flavour crisps and I run this method, inputting "salt" as the flavour, it just returns 0 as though there are no PackOfCrisps objects with flavour "salt".
Sorry if this doesn't make sense. I am very new to Java and I have tried to explain my problem the best I can. :)
The list packets holds PackOfCrisps objects, and the method takes a String parameter. So the statement packets.get(n).equals(flavour) is comparing a PackOfCrisps object to a String, hence the count variable will never increase.
You need to compare the flavour string to the specific field of the object, something like:
if(packets.get(n).getFlavour().equals(flavour)){
On a side note, you can replace the while loop with a simple for loop and remove the increment of n.
There is a built-in solution to your problem, you can use this method
You can rewrite your countPacks method like this :
public int countPacks(String flavour){
return Collections.frequency(packets, flavour);
}

Java 8 Stream.findAny() vs finding a random element in the stream

In my Spring application, I have a Couchbase repository for a document type of QuoteOfTheDay. The document is very basic, just has an id field of type UUID, value field of type String and created date field of type Date.
In my service class, I have a method that returns a random quote of the day. Initially I tried simply doing the following, which returned an argument of type Optional<QuoteOfTheDay>, but it would seem that findAny() would pretty much always return the same element in the stream. There's only about 10 elements at the moment.
public Optional<QuoteOfTheDay> random() {
return StreamSupport.stream(repository.findAll().spliterator(), false).findAny();
}
Since I wanted something more random, I implemented the following which just returns a QuoteOfTheDay.
public QuoteOfTheDay random() {
int count = Long.valueOf(repository.count()).intValue();
if(count > 0) {
Random r = new Random();
List<QuoteOfTheDay> quotes = StreamSupport.stream(repository.findAll().spliterator(), false)
.collect(toList());
return quotes.get(r.nextInt(count));
} else {
throw new IllegalStateException("No quotes found.");
}
}
I'm just curious how the findAny() method of Stream actually works since it doesn't seem to be random.
Thanks.
The reason behind findAny() is to give a more flexible alternative to findFirst(). If you are not interested in getting a specific element, this gives the implementing stream more flexibility in case it is a parallel stream.
No effort will be made to randomize the element returned, it just doesn't give the same guarantees as findFirst(), and might therefore be faster.
This is what the Javadoc says on the subject:
The behavior of this operation is explicitly nondeterministic; it is free to select any element in the stream. This is to allow for maximal performance in parallel operations; the cost is that multiple invocations on the same source may not return the same result. (If a stable result is desired, use findFirst() instead.)
Don’t collect into a List when all you want is a single item. Just pick one item from the stream. By picking the item via Stream operations you can even handle counts bigger than Integer.MAX_VALUE and don’t need the “interesting” way of hiding the fact that you are casting a long to an int (that Long.valueOf(repository.count()).intValue() thing).
public Optional<QuoteOfTheDay> random() {
long count = repository.count();
if(count==0) return Optional.empty();
Random r = new Random();
long randomIndex=count<=Integer.MAX_VALUE? r.nextInt((int)count):
r.longs(1, 0, count).findFirst().orElseThrow(AssertionError::new);
return StreamSupport.stream(repository.findAll().spliterator(), false)
.skip(randomIndex).findFirst();
}

Returning an arraylist and iterating throught the returned list

Im trying to return an arraylist from the method getNumbers (which contains strings)
public ArrayList<String> getNumbers(){
return (numeros);
}
Then by using a searcher im trying to compare between a variable m (which contains the desired info to look for) and the returned list.
public class NumberSearcher {
Reader reader = new KeyboardReader();
public NumberSearcher(ArrayList<Contacto> contactos){
String m = reader.read();
for(int i = 0; i<contactos.size();i++){
if(contactos.get(i).getPhoneNumbers().contains(m)){
contactos.get(i).display();
}
}
}
}
I have succeded in creating a searcher using this very same style but only when using methods that return String alone.
The problem is its not working. If there there would be a match it should display the contact information but it seem it isnt "comparing" properly because nothing happens.
It's difficult to understand what you're asking here. Your getNumbers method doesn't get called from the second code block, so I don't see where that is relating to anything. It's also unclear what you mean the problem is. Can you try to give us a more detailed description of what is going wrong?
Anyways, I'll try to give you some general advice here, but without knowing the issue it's hard to say how much this will help.
Firstly, it is almost always recommended to have your method's return type as the List interface, rather than a specific implementation (ArrayList, etc). You can specify a return type from within the method but this way they client doesn't need to know what the underlying data structure is, and you are also flexible to future data structure changes.
public List<String> getNumbers(){
return (numeros);
}
Secondly, I would probably change the name 'getNumbers' to something slightly more precise - if I see a 'getNumbers' method I expect it to return some numeric entities, not a list of strings. If they are phone numbers then explicity call it 'getPhoneNumbers'.
Though I'm not entirely sure I understand what you asking, I think this may solve your issues:
for(int i = 0; i < contactos.size(); i++) {
Contacto next = contactos.get(i);
if(next.getEmails().contains(m)) {
next.display();
}
}
And as an afterthought, is there any specific reason you're only checking string containment? I would suggest that you check case-insensitive equality unless you really do want to find out if the string just contains the element.
Is this what you are looking for?
public class EmailSearcher {
Reader reader = new KeyboardReader();
public EmailSearcher(ArrayList<Contacto> contactos){
while(reader.read() != 'keyThatTerminates') {
String m = reader.read();
for(int i = 0; i<contactos.size();i++){
var row = contactos.get(i);
if(row.getEmails().contains(m)){
row.display();
}
}
}
}
}

Remove all 10s in a list and append a same number of 0s to the list at the end in JAVA

I've done most part of this. Anyone give me a small hint about how do I find the number of 10s in the list.
Eg. Input would be
[10,4,6,10,6,7]
Output must be
[4,6,6,7,0,0]
import java.util.ArrayList;
import java.util.List;
public class prob64 {
public static List output;
public static void getVal(List ll)
{
int count=0;
List ll1=new ArrayList();
for(int i=0;i<ll.size();i++)
{
if((int)ll.get(i)!=10)
{
ll1.add(ll.get(i));
}
if((int)ll.get(i)==10)
{
count++;
}
}
if(count>0)
{
ll1.add(8);
}
output=ll1;
System.out.println(output);
}
public static void main(String[] args) {
List<Integer> ll=new ArrayList();
ll.add(10);
ll.add(1);
ll.add(10);
ll.add(2);
prob64.getVal(ll);
}
}
The current output I'm getting is [1,2,0]. I'm supposed to get [1,2,0,0]
List.remove(Object) removes the first matching element. It also returns a boolean indicating if a removal was really done, so this should work :
while(ll.remove(10)) {
ll.add(0);
}
That is, as long as you find 10s to remove, add 0s. Note that List.add adds the element at the end of the list, which is your requirement (if I'm correct).
I suppose this is some kind of learning exercise, but I would advise you to find better names for your variable (ll & ll1 does not make your function easy to read).
You are adding only one zero at the end of the loop (in case 10s were found). You should count the number of 10s then add zeros as much as this number. Your program should look something like this:
int count=0;
List ll1=new ArrayList();
for(int i=0;i<ll.size();i++)
{
if((int)ll.get(i)!=10)
ll1.add(ll.get(i));
else
count++;
}
for(int j=0; j<count;j++)
ll1.add(0);
If count is number of 10's to add, use:
for(int j=0; j<count;j++){
ll1.add(8); // or ll1.add(0); ???
}
Few points to add to what others have mentioned above
I don't see any reason why you must define the output List to be static. When you define something(variables/functions) as static they are owned by the class rather that the objects and also it is a good programming practice not to change them using instance functions.What I mean is if you wish only to print there is no need of that output instance variable. You can directly print ll1.
Please use Generics in your code. When you know all you have in your list are integers specify it - Even in the function getVal(). I don't know how your code is compiling but you cannot cast Object to an int.
(int)ll.get(i)!=10
This code will fail. Try using Integer instead of int.
Your problem statement read replacing all 10's with 0's. So why are you adding 8 instead.It must be
ll1.add(0);
As other have specifies you need to add 0 as many time as your count is. So another loop is needed. Rest all look good.

Tutorials for Java errors and syntax

I am asking for help on self-help, which is kind of an oxymoron. How do I bug you nice folks less by solving more of my own problems?
I am in my last week of Java programming and I am having a huge hurdle with learning Java. I have read all the books but I keep getting hung up on tiny little issues. It is like trying to build a house of cards. I only know about the parts of the syntax and the uses that the book shows. When I am combining things, I run into horrible hurdles. I try for hours of tinkering to figure them out. The sun docs only show basic uses that don't seem to help
Here is what I would like:
When I am trying something and it doesn't work like the following manipulations of an array list, I want to find a place or program that can show examples code of things like adding an additional class instance to an arrayList. Where can I learn concisely about this without having to ask a question or 2 for every syntax error? Where is the Google for Java? Is there a program that will take your errors and show you how to fix them (or offer suggestions)?
/tmp/jc_4083/Inventory.java:101: incompatible types
found : RatedDVD[]
required: java.util.ArrayList
dvdlist = temp;
^
/tmp/jc_4083/Inventory.java:110: array required, but java.util.ArrayList found
if (p != dvdlist[i]) {
^
/tmp/jc_4083/Inventory.java:111: array required, but java.util.ArrayList found
temp[i-adj] = dvdlist[i];
^
/tmp/jc_4083/Inventory.java:115: incompatible types
found : RatedDVD[]
required: java.util.ArrayList
dvdlist = temp;
Here is my code for this class if anyone is interested in looking at it for me:
//Contruct inv and allow for methods add, get, size, sort, and value
import java.util.*;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
public class Inventory
{// class Inventory
private ArrayList<RatedDVD> dvdlist;// declare dvdlist as ArrayList of RatedDVD
private int numDVDs;
public Inventory()
{// method Inventory
dvdlist = new ArrayList<RatedDVD>();
}// end method
// add & get
public RatedDVD get(int i){return dvdlist.get(i);}// method get
public void add(DVD d){
dvdlist = dvdlist d;
sort();
}// method add
public double value()
{// method value
double total = 0.0;
for (int i = 0; i < dvdlist.size(); i++)
{// for every pass thru dvdlist add total
// [DEBUG] consider enhanced for
total += get(i).feeValue();
}
return total;
}// end method value
public void sort()
{// method sort
// [DEBUG] consider optimization
int n = dvdlist.size();
for (int search = 1; search < n; search++)
{// for do the following and increment till dvdlist has been searched
for (int i = 0; i < n-search; i++)
{// for step through comparison for entire dvdlist
if (dvdlist.get(i).getName().compareToIgnoreCase(dvdlist.get(i+1).getName()) > 0)
{// if swap necessary then swap
RatedDVD temp = dvdlist.get(i);
dvdlist.set(i,dvdlist.get(i+1));
dvdlist.set(i+1,temp);
}// end if swap
}// end for compareto
}// end outer for
}// end method sort
public int size(){return dvdlist.size();}// method size
public void save() {
save(true);
}
// save it to C:\data\inventory.dat
public void save(boolean saveagain) {
try {
BufferedWriter w = new BufferedWriter(new FileWriter("c:\\data\\inventory.dat"));
for (int i = 0; i < size(); i++) {
RatedDVD dvd = get(i);
w.write( dvd.getItem() + "\n");
w.write( dvd.getName() + "\n");
w.write( dvd.getRating() + "\n");
w.write( dvd.getUnits() + "\n");
w.write( dvd.getPrice() + "\n");
w.write( dvd.value() + "\n");
w.write( dvd.fee() + "\n");
w.write( dvd.feeValue() + "\n");
w.newLine();
}
// total value of it
//w.write( value() + "\n");
w.close();
} catch (Exception ex) {
if (saveagain) {
new File("c:\\data\\").mkdir(); // make file if doesn't exist
save(false);
}
}
}
public int search(String name) {
for (int i = 0; i < size(); i++) { // check if name string is equal
if (get(i).getName().equalsIgnoreCase(name)) return i;
}
return -1; // we didn't find anything
}
// add a new dvd to the end, increasing the array size
public void add(RatedDVD p) {
RatedDVD[] temp = new RatedDVD[dvdlist.size()+1];
for (int i = 0; i < dvdlist.size(); i++) {
temp[i] = dvdlist[i];
}
temp[temp.length-1] = p; // add it at the end
dvdlist = temp;
}
// remove a DVD from the array, and shrink the array size
public void delete(RatedDVD p) {
RatedDVD[] temp = new RatedDVD[dvdlist.size()-1];
int adj = 0;
for (int i = 0; i < dvdlist.size(); i++) {
if (p != dvdlist[i]) {
temp[i-adj] = dvdlist[i];
}
else adj = 1;
}
dvdlist = temp;
}
public int highestNumber() {
int numb = 0;
for (int i = 0; i < dvdlist.size(); i++) {
if (get(i).getItem() > numb) {
numb = get(i).getItem();
}
}
return numb;
}
}// end class inventory
The dvdlist is an ArrayList, which implements the Collection interface, not an Array (BTW, and this is known as the "program to an interface, not an implementation" principle, you should decalare dvdlist as a java.util.List):
private ArrayList<RatedDVD> dvdlist;// declare dvdlist as ArrayList of RatedDVD
Have a look at the methods on the Collection interface, you'll find everything you need for adding and removing elements.
So, to add a RatedDVD, you don't need to use a temporary array of RatedDVD that won't fit anyway into an ArrayList like you're doing here:
// add a new dvd to the end, increasing the array size
public void add(RatedDVD p) {
RatedDVD[] temp = new RatedDVD[dvdlist.size()+1];
for (int i = 0; i < dvdlist.size(); i++) {
temp[i] = dvdlist[i];
}
temp[temp.length-1] = p; // add it at the end
dvdlist = temp;
}
Instead, just call the add(Object o) method on dvdlist.
To delete a RatedDVD instance, use the remove(Object o) method on dvdlist.
For the search() method, consider using contains(Object o) on dvdlist.
If you need to iterate over a collection, use an Iterator:
for (Iterator iter = dvdlist.iterator(); iter.hasNext();) {
RatedDVD ratedDVD = (RatedDVD) iter.next();
//rest of the code block removed
}
Or even faster now with Java 5+ and Generics:
for (RatedDVD ratedDVD : dvdlist) {
// rest of the code here
}
Really, you need to dig the the Collection Framework.
The compiler errors seem to be quite descriptive of what you're doing wrong, but I can see why you might be confused about how to do it right. You seem to be misunderstanding how an ArrayList is meant to be used. If you look at the docs, you will see it has methods add() and remove() that do the operations you've created add() and delete() methods for. You're attempting to treat the ArrayList as if it is a raw array. Don't do that; use the methods provided by the API. Not only will this solve your errors, but it will make your code cleaner and clearer to future programmers.
Actually, the compiler error is very clear:
/tmp/jc_4083/Inventory.java:101: incompatible types
found : RatedDVD[]
required: java.util.ArrayList
dvdlist = temp;
It says "incompatible types" and that it expected a java.util.ArrayList but found instead a RatedDVD[].
Your problem is simply that, unlike in languages like Python, Java does not treat lists and arrays interchangeably. They are completely different things - arrays are special language-level constructs, while ArrayList is a class like any other.
So you cannot assign an array to a variably of type list. You either have to decide on using only one of these two types throughout your program, or you have to convert between them manually, using methods such as java.util.Arrays.asList() and List.toArray().
It seems that you're trying to do too advanced things too fast - you should probably look at Sun's Java tutorials first - though they are quite comprehensive and can also be used as a reference for looking up language details. There is also a section about conversion between collections and arrays.
I suggest you use an IDE (like Eclipse, entirely free). It will help you through the API syntax by making suggestions as you type, and show you errors when you type them, so that you can pinpoint exact syntax errors and ask about them. In terms of asking, that is what StackOverflow is for.
Others beat me to your specific syntax question, so I'm just limiting my answer to the general question of how you get help.
To resolve compiler errors, usually it's best to start with the first one and fix it first. After fixing that, the rest of the compiler errors might also be solved, or they might be different kinds of errors.
To understand what some compiler error means, there is an article called Compile and Runtime Errors in Java (PDF) that goes through different kinds of error messages and gives examples of what kind of code may cause them. And as for runtime error messages, Java Glossary has quite a big list of them. They also have a list of compile-time error messages.
So, your problem here is that you're trying to access an ArrayList like an array, which is incorrect because Java doesn't do stuff like that. You need to use list.get(i) to get the ith element in an Array. Similarly, when you tried to set an ArrayList variable to an array, the compiler got mad at you. You need to create a new ArrayList with the contents of temp and then set dvdlist to that, eg. dvdlist = new ArrayList<RatedDVD>(temp);.
As for your continued problems: There is an API Specification for Java which tells you basically how to use all the classes that are included in the Java API. For example, ArrayList is a generic collection which has certain methods and constructors that you need to use. Java does not have operator overloading, so you can't just access elements in a List using array syntax. Also, arrays are their own data type so you can't just treat an ArrayList as an array and vice versa.
It looks like you are confused about the difference between an array and an ArrayList. An array is a static list of elements, and is constructed using the [] symbols. An ArrayList is an object in the Collections system in Java that acts like a size-modifiable array - i.e. it can be indexed into, and can be added onto, inserted into, etc. They are not interchangable.
As to where you can look, etc. If this is your first programming experience, you are not alone. Many compiler errors are less than helpful. One suggestion I can give you that I learned through many years of trial and error - start small and build up. Get a main method that compiles. Then add the first little piece (creating a class for instance). Then add the next piece, and so on. Test as you go, etc. You can google for particular compiler errors - I have been surprised what I have found. Beyond that, a lot of it is trial and error - these are things you learn from experience, and a lot of the speed of "old hands" comes from the long experience of seeing what you can do wrong over and over again, not any sort of innate intelligence. I totally understand your frustration - I felt that way when I was starting out about 15 years ago now (but I was on Borland Pascal - yuck).
One of the biggest issues beginning programmers seem to have is not being able to read and interpret error messages very well.
You would be well served by carefully examining the errors that javac (or any compiler/interpreter) provides. Maybe even start by making some mistakes that you understand in your code (ie, assign an incorrect typed value to a variable, extend a loop beyond the bounds) and see how your compiler handles these.
Try to think in object oriented terms...
It looks to me that something (classwork, I guess) has pushed you into writing an object-oriented program but it's possible that you haven't yet accepted that you will need to think in those terms.
In Java most things are objects, but Java supports primitive types, and arrays of both. It's possible to program in Java in a flat, procedural, mutable way, but also possible to write in an object-oriented functional way. It's possible to do both and get confused, which is where you may be right now.
You are trying to mix the two styles. This isn't always a bad thing, but for coursework we can safely bet the farm that your instructor will want to see more objects and fewer arrays, unless those arrays are the private internal implementation of an object.
So think of the data structures as black boxes with methods, and then see how what you are doing is implementing one yourself.
You have probably been here, but these are the things that you can do with an ArrayList. And you have an ArrayList<RatedDVD> which further restricts what you can do with it. Try to understand this first, and then fix the program to work with the available operations on an ArrayList object.

Categories