Method declaration in java - return

I have a question regarding this code, you can see in some methods that there are comments with a return, that is because I think I have to use a return method instead of a void method. My teacher told me to transform them to a void class, but isn't a method which modifies field variables suposed to return something? I'm in doubt because sometimes my teacher seems to not know so much about programming or has some doubts so, thank for your help beforehand.
public class ArraysClass {
private int[] array;
private int arrayLength;
public ArraysClass() {
setArrayLength();
array = new int[arrayLength];
}
public int setArrayLength() {
Scanner scanner = new Scanner(System.in);
System.out.println("Enter a number to set the length of the array:");
arrayLength = scanner.nextInt();
System.out.println();
return arrayLength;
}
public void fillArray() {
Scanner scanner = new Scanner(System.in);
for (int i = 0; i < arrayLength; i++) {
System.out.println("Type a number to fill position " + i);
array[i] = scanner.nextInt();
}
// return array;
System.out.println();
}
public void findNumber() {
Scanner scanner = new Scanner(System.in);
int tofind, position;
System.out.println("Enter a number to search it in the array:");
tofind = scanner.nextInt();
position = Arrays.binarySearch(array, tofind);
if (position < 0) {
System.out.println("We did not find your number.");
} else {
System.out.println("The number you typed is in the next position: " + position);
}
System.out.println();
}
public void fillMethod() {
Scanner scanner = new Scanner(System.in);
int tofill;
System.out.println("Enter a number to fill the entire array with:");
tofill = scanner.nextInt();
Arrays.fill(array, tofill);
System.out.println();
//return array;
}
public void Sortmethod() {
Arrays.sort(array);
//return array;
}
private void showArray() {
System.out.println("Showing the array...");
for (int i = 0; i < arrayLength; i++) {
System.out.println(array[i]);
}
System.out.println();
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
ArraysClass arrayobj = new ArraysClass();
int choose;
do {
do {
System.out.println("1-Fill the array");
System.out.println("2-Find a number in the array");
System.out.println("3-Fill the entire array with a number");
System.out.println("4-Sort the array");
System.out.println("5-Show the array");
System.out.println("6-Exit");
System.out.println("Which one do you want to use?:");
choose = scanner.nextInt();
} while (choose < 1 && choose > 6);
switch (choose) {
case 1:
arrayobj.fillArray();
break;
case 2:
arrayobj.findNumber();
break;
case 3:
arrayobj.fillMethod();
break;
case 4:
arrayobj.Sortmethod();
break;
case 5:
arrayobj.showArray();
break;
case 6:
break;
}
} while (choose != 6);
}
}

In general, a method should return something if you need value from it. It is an approach used by some programmers to return a boolean even for do-only methods for success or failure or an int, for a status code. I do not follow these approaches. When I implement a method, I always ask myself how would I like to use that method. If I need a value from it, then it will have its type. Otherwise, it will be void. Let us see your methods:
setArrayLength: In general, from this name I would expect that you pass an int to it, representing the length and the method to be void. This is very common for setters, but here you are reading the actual value inside the method which is clearly inferior compared to having an int parameter, as your method will be useless if one wants to set the array length using a value not read from the console.
fillArray: I would expect this to be void, so I agree with its declaration, but again, the reading part should not be here.
findNumber: Should get the number to be found as a parameter and return an int, which represents its index, -1 if not found.
fillMethod: Should be void and should have an int parameter, which represents the value to be used to fill the array.
sortMethod: ok, maybe return the resulting array, but depends on your needs.
showArray: I would expect a PrintStream there, you will not necessarily output to System.out
General mistake: You mix methods with in/out operations to the console, the code is not general enough this way.

Related

Stream Data Calculation In Flux

The following code illustrates a logic I need in a Spring Reactive project:
Inputs:
var period = 3;
int [] inArr = {2, 4, 6, 7, 9, 11, 13, 16, 17, 18, 20, 22 };
Calculation:
var upbond = inArr[0] + period;
var count =0;
List<Integer> result = new ArrayList();
for(int a: inArr){
if(a <= upbond){
count++;
}else{
result.add(count);
count = 1;
upbond += period;
}
}
result.add(count);
System.out.println(Arrays.toString(result.toArray()));
The data source of the sorted integers is the Flux from DB where it shall continually fetch data once a new suitable data is written into the DB. And the result shall be a stream that is sending out to another node through RSocket (by the request-stream communication mode).
After some online searching on Reactor, including some tutorials, I still can't figure out how to write the logic in the Flux fashion. The difficulty I have is that those calculations on data defined outside of the loop.
How shall I approach it in the Reactor?
The scan() variant that lets you use a separately typed accumulator is your friend here.
I'd approach this with a separate State class:
public class State {
private int count;
private Optional<Integer> upbond;
private Optional<Integer> result;
public State() {
this.count = 0;
this.upbond = Optional.empty();
this.result = Optional.empty();
}
public State(int count, int upbond) {
this.count = count;
this.upbond = Optional.of(upbond);
this.result = Optional.empty();
}
public State(int count, int upbond, int result) {
this.count = count;
this.upbond = Optional.of(upbond);
this.result = Optional.of(result);
}
public int getCount() {
return count;
}
public Optional<Integer> getUpbond() {
return upbond;
}
public Optional<Integer> getResult() {
return result;
}
}
...and then use scan() to build up the state element by element:
sourceFlux
.concatWithValues(0)
.scan(new State(), (state, a) ->
a <= state.getUpbond().orElse(a + period) ?
new State(state.getCount() + 1, state.getUpbond().orElse(a + period)) :
new State(1, state.getUpbond().orElse(a + period) + period, state.getCount())
)
.windowUntil(s -> s.getResult().isPresent())
.flatMap(f -> f.reduce((s1, s2) -> s1.getResult().isPresent()?s1:s2).map(s -> s.getResult().orElse(s.getCount() - 1)))
Aside: The concatWithValues() / windowUntil() / flatMap() bits are there to handle the last element - there's probably a cleaner way of achieving that, if I think of it I'll edit the answer.
I think scan is definitely the right tool here, combined with a stateful class, although my approach would be slightly different than Michaels.
Accumulator:
class UpbondAccumulator{
final Integer period;
Integer upbond;
Integer count;
Boolean first;
Queue<Integer> results;
UpbondAccumulator(Integer period){
this.period = period;
this.count = 0;
this.upbond = 0;
this.results = new ConcurrentLinkedQueue<>();
this.first = true;
}
//Logic is inside accumulator, since accumulator is the only the only thing
//that needs it. Allows reuse of accumulator w/o code repetition
public UpbondAccumulator process(Integer in){
//If impossible value
//Add current count to queue and return
//You will have to determine what is impossible
//Since we concat this value on the end of flux
//It will signify the end of processing
//And emit the last count
if(in<0){
results.add(count);
return this;
}
//If first value
//Do stuff outside loop
if(this.first) {
upbond = in + period;
first=false;
}
//Same as your loop
if(in <= upbond)
count++;
else {
results.add(count);
count = 1;
upbond += period;
}
//Return accumulator
//This could be put elsewhere since it isn't
//Immediately obvious that `process` should return
//the object but is simpler for example
return this;
}
public Mono<Integer> getResult() {
//Return mono empty if queue is empty
//Otherwise return queued result
return Mono.justOrEmpty(results.poll());
}
}
Usage:
dbFlux
//Concat with impossible value
.concatWithValues(-1)
//Create accumulator, process value and return
.scan(new UpbondAccumulator(period), UpbondAccumulator::process)
//Get results, note if there are no results, this will be empty
//meaning it isn't passed on in chain
.flatMap(UpbondAccumulator::getResult)
Following comment from Michael here is an immutable approach
Accumulator:
public class UpbondAccumulator{
public static UpbondState process(int period,Integer in,UpbondState previous){
Integer upbond = previous.getUpbond().orElse(in + period);
int count = previous.getCount();
if(in<0) return new UpbondState(upbond, count, count);
if(in <= upbond) return new UpbondState(upbond,count + 1 , null);
return new UpbondState(upbond + period, 1, count);
}
}
State object:
public class UpbondState {
private final Integer upbond;
private final int count;
private final Integer result;
public UpbondState() {
this.count = 0;
this.upbond = null;
this.result = null;
}
public UpbondState(Integer upbond, int count,Integer result) {
this.upbond = upbond;
this.count = count;
this.result = result;
}
public int getCount() { return count; }
public Optional<Integer> getUpbond() { return Optional.ofNullable(upbond); }
public Integer getResult() { return result; }
public boolean hasResult() { return result!=null; }
}
Usage:
dbFlux
.concatWithValues(-1)
.scan(new UpbondState(),
(prev, in) -> UpbondAccumulator.process(period,in,prev))
//Could be switched for Optional, but would mean one more map
//+ I personally think makes logic less clear in this scenario
.filter(UpbondState::hasResult)
.map(UpbondState::getResult)

Performance of sequential stream

I read the "when to use parallel stream?" by DougLea et.al http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html.
I wonder did any one had a guide lines(do's/ don't dos)/ observations which felt them that old way of coding is better in some cases than sequential stream?
I found one here https://jaxenter.com/java-performance-tutorial-how-fast-are-the-java-8-streams-118830.html
I know it's a abstract question but it will be helpful if somebody can share their experience in performance of seq stream vs java 7 way
I've done this just a few days ago; we had to sum a very large array and was wondering what would be the fastest way to do it - so I measured (don't guess; I've used jmh):
#State(Scope.Thread)
public static class Holder {
#Param({ "1000", "10000", "50000", "100000", "1000000" })
public int howManyEntries;
int array[] = null;
#Setup
public void setUp() {
array = new int[howManyEntries];
for (int i = 0; i < howManyEntries; ++i) {
array[i] = i;
}
}
#TearDown
public void tearDown() {
array = null;
}
}
#Fork(1)
#Benchmark
public int iterative(Holder holder) {
int total = 0;
for (int i = 0; i < holder.howManyEntries; ++i) {
total += holder.array[i];
}
return total;
}
#Fork(1)
#Benchmark
public int stream(Holder holder) {
return Arrays.stream(holder.array).sum();
}
#Fork(1)
#Benchmark
public int streamParallel(Holder holder) {
return Arrays.stream(holder.array).parallel().sum();
}
The winner is always the old style java-7 way.
// 1000=[iterative, stream, streamParallel]
// 10000=[iterative, stream, streamParallel]
// 50000=[iterative, stream, streamParallel]
// 100000=[iterative, stream, streamParallel]
// 1000000=[iterative, stream, streamParallel]
Even for 1 million elements. But the result differs in up to 60 ms - if that bites you or not is entirely your choice.
Streams are not meant for speed, they will not replace the old style, neither do they want to - it could add extra visibility to your code for example.

How to set values of global variables used in function parameters

I can conveniently change opsCount variable directly from inside the function,
because there is only one of that type of variable.
int opsCount = 0;
int jobXCount = 0;
int jobYCount = 0;
int jobZCount = 0;
void doStats(var jobCount) {
opsCount++;
jobCount++;
}
main() {
doStats(jobXCount);
}
But there are many jobCount variables, so how can I change effectively that variable, which is used in parameter, when function is called?
I think I know what you are asking. Unfortunately, the answer is "you can't do this unless you are willing to wrap your integers". Numbers are immutable objects, you can't change their value. Even though Dart's numbers are objects, and they are passed by reference, their intrinsic value can't be changed.
See also Is there a way to pass a primitive parameter by reference in Dart?
You can wrap the variables, then you can pass them as reference:
class IntRef {
IntRef(this.val);
int val;
#override
String toString() => val.toString();
}
IntRef opsCount = new IntRef(0);
IntRef jobXCount = new IntRef(0);
IntRef jobYCount = new IntRef(0);
IntRef jobZCount = new IntRef(0);
void doStats(var jobCount) {
opsCount.val++;
jobCount.val++;
}
main() {
doStats(jobXCount);
print('opsCount: $opsCount; jobXCount: $jobXCount; jobYCount: $jobYCount; jobZCount: $jobZCount');
}
EDIT
According to Roberts comment ..
With a custom operator this would look like:
class IntRef {
IntRef(this.val);
int val;
#override
String toString() => val.toString();
operator +(int other) {
val += other;
return this;
}
}
void doStats(var jobCount) {
opsCount++;
jobCount++;
}

Using scanner to read phrases

Hey StackOverflow Community,
So, I have this line of information from a txt file that I need to parse.
Here is an example lines:
-> date & time AC Power Insolation Temperature Wind Speed
-> mm/dd/yyyy hh:mm.ss kw W/m^2 deg F mph
Using a scanner.nextLine() gives me a String with a whole line in it, and then I pass this off into StringTokenizer, which then separates them into individual Strings using whitespace as a separator.
so for the first line it would break up into:
date
&
time
AC
Power
Insolation
etc...
I need things like "date & time" together, and "AC Power" together. Is there anyway I can specify this using a method already defined in StringTokenizer or Scanner? Or would I have to develop my own algorithm to do this?
Would you guys suggest I use some other form of parsing lines instead of Scanner? Or, is Scanner sufficient enough for my needs?
ejay
oh, this one was tricky, maybe you could build up some Trie structure with your tokens, i was bored and wrote a little class which solves your problem. Warning: it's a bit hacky, but was fun to implement.
The Trie class:
class Trie extends HashMap<String, Trie> {
private static final long serialVersionUID = 1L;
boolean end = false;
public void addToken(String strings) {
addToken(strings.split("\\s+"), 0);
}
private void addToken(String[] strings, int begin) {
if (begin == strings.length) {
end = true;
return;
}
String key = strings[begin];
Trie t = get(key);
if (t == null) {
t = new Trie();
put(key, t);
}
t.addToken(strings, begin + 1);
}
public List<String> tokenize(String data) {
String[] split = data.split("\\s+");
List<String> tokens = new ArrayList<String>();
int pos = 0;
while (pos < split.length) {
int tokenLength = getToken(split, pos, 0);
tokens.add(glue(split, pos, tokenLength));
pos += tokenLength;
}
return tokens;
}
public String glue(String[] parts, int pos, int length) {
StringBuilder sb = new StringBuilder();
sb.append(parts[pos]);
for (int i = pos + 1; i < pos + length; i++) {
sb.append(" ");
sb.append(parts[i]);
}
return sb.toString();
}
private int getToken(String[] tokens, int begin, int length) {
if (end) {
return length;
}
if (begin == tokens.length) {
return 1;
}
String key = tokens[begin];
Trie t = get(key);
if (t != null) {
return t.getToken(tokens, begin + 1, length + 1);
}
return 1;
}
}
and how to use it:
Trie t = new Trie();
t.addToken("AC Power");
t.addToken("date & time");
t.addToken("date & foo");
t.addToken("Speed & fun");
String data = "date & time AC Power Insolation Temperature Wind Speed";
List<String> tokens = t.tokenize(data);
for (String s : tokens) {
System.out.println(s);
}

String Pattern matching in Blackberry

How i can do a simple pattern matching in blackberry OS 6.0. The purpose is to check whether the user name entered to the UserName edit field contains special characters.... plz help me
thanks jibysthomas
A better solution would be to control the user input by adding an appropriate TextFilter to your edit field. That has the added benefit of modifying the on-screen keyboard to match your filter on those devices so equipped.
Here is an example combining the action of two built in text filters to make one that only allows upper letters and numbers:
import net.rim.device.api.ui.text.TextFilter;
import net.rim.device.api.system.Characters;
/**
* A TextFilter class to filter for station identifiers
*/
private static class StationFilter extends TextFilter {
// Order of the supporting filters is important, NUMERIC will convert
// letters to numbers if it gets them first.
private static TextFilter[] _tf = {
TextFilter.get(TextFilter.NUMERIC),
TextFilter.get(TextFilter.UPPERCASE)
};
// Convert using the first supporting filter that has a conversion
public char convert( char character, int status) {
char c = 0;
for (int i = _tf.length - 1; i >= 0; i--) {
c = _tf[i].convert(character, status);
if (c != 0) {
return c;
}
}
return 0;
}
// Validate a space for separator, then by supporting filter
public boolean validate(char character) {
if (character == Characters.SPACE) {
return true;
}
for (int i = _tf.length - 1; i >= 0; i--) {
boolean b = _tf[i].validate(character);
if (b) {
return true;
}
}
return false;
}
}

Resources