CS503: First Lecture, Fall 2008

Download Report

Transcript CS503: First Lecture, Fall 2008

CS503: Second Lecture, Fall 2008
Basic Java, OOP, and Arrays.
Michael Barnathan
Here’s what we’ll be learning:
• Java:
– Constants (using final).
– Member variables of a class.
• So far, all of the variables you worked with were local to the main() function.
– Methods and constructors (similar in C++).
– Static variables (using static, also in C++).
– “Public”, “private”, and “package” access and the concept of least
privilege (also in C++).
– “Encapsulation” (general OOP technique).
• Theory:
– Unsorted Arrays.
• “CRUD” operations: Create/read/update/delete.
• Linear searching.
• Fixed vs. variable size arrays.
– “Growing”/“Doubling” strategy.
Back to the Guessing Game
• Here’s the code for the game itself:
import java.util.Scanner;
class GuessingGame {
public static void main(String[] args) {
final int maxnum = 100;
//Highest number we're going to guess to.
//I'm thinking of a number...
int number = (int) ((Math.random() * maxnum) + 1);
System.out.println("I'm thinking of a number between 1 and " + maxnum);
Scanner readnums = new Scanner(System.in);
int guess = 0;
while (guess != number) {
System.out.print("What do you think it is? ");
guess = readnums.nextInt();
if (guess < number)
System.out.println("Nope, higher!");
else if (guess > number)
System.out.println("Nope, lower!");
else
System.out.println("You got it!");
}
}
}
The other side of the game…
• You manually executed an algorithm to try and
guess the number in the previous class.
• Today, we’ll try to write a program that will do
it in Java. You are given the following class:
public class Guesser {
public static final int MAXNUM = 100;
private final int secret;
//Generate the secret number in the constructor.
public Guesser() { secret = (int) (Math.random() * MAXNUM + 1); }
//Returns < if the number is less than the guess, > if greater, = if equal.
//This uses the “ternary operator” – which is just a concise way to write if/else statements.
public char guessNumber(int guess) { return (secret > guess) ? ‘>’ : ((secret < guess) ? ‘<’ : ‘=’); }
}
This has some new things that we need to know before writing anything.
Member variables.
public class Guesser {
public static final int MAXNUM = 100;
private final int secret;
…
}
• So far, we’ve only worked with local variables inside of main().
– Local variables belong to a block of code inside of a function. They go out of scope at the
end of that block.
• These are member variables of class Guesser, which means that they
belong to the class, not just a function inside of the class.
– They will stay in scope as long as their Guesser object does.
– Makes sense: they’re declared outside of any functions.
• They can be public, private, or protected. I’ll explain this later.
Final Variables
•
•
•
You declare constants using the final keyword in Java.
Both local and member variables can be final.
final variables may be set only once.
– Once they have a value assigned, it is an error to assign another value to them.
•
They are like const variables in C, with one important difference:
– They do not need to be declared and initialized in the same statement.
•
The following is valid in Java:
– final int secret;
– secret = 50;
•
But the following is not valid in C:
– const int secret;
– secret = 50;
•
//Nope, you need to set it above.
The following is not valid in either language:
– final int secret = 50;
– secret = 51;
•
//Declaration.
//Initialization.
Why is this an important difference?
– Constructors.
//This is fine.
//No; it must always be 50 now.
Methods
• A method is a function inside of a class.
• All functions in Java are methods.
– You can’t define functions outside of classes, like you could in
C/C++.
• Like variables, methods can be public, private, or protected.
Again, we’ll speak of this later.
• You’ve already written one: main.
• You’ve already invoked several:
– Scanner.nextInt()
– Math.random()
• Like member variables, you use the “.” operator to call
methods in Java.
Constructors
• A constructor is a special method that is called when an object is created.
– They are usually used to initialize an object’s member data.
• Constructors always have the same name as their class and never return
anything.
– Not even void.
• They can take arguments. A constructor without arguments is called a
default constructor.
• Example constructors:
class Guesser {
private final int secret;
Guesser() { secret = (int) (Math.random() * MAXNUM + 1); }
Guesser(int s) { secret = s; }
//Default constructor.
}
• This is why you must be able to set final variables later in Java – they are
often set inside of constructors.
• If you don’t specify a constructor, Java will give your class an empty one by
default.
– If you specify any constructor, even one with arguments, Java won’t give you a
default one anymore. You must implement it yourself if you want it.
Access: public, private, package.
• Both data and methods have access levels.
• 4 levels: private, package, protected, public.
• Private:
• Only methods within the same class can access a private member variable or method.
• Package:
• Only methods within the same package (group of classes) can access these variables.
•
We’ll discuss packages a bit later.
• This is the default level; i.e., what you get when you leave out a “private”, “public”, or
“protected” keyword in a declaration.
• Protected:
• Only members within the same package or a class that inherits from the same class have
access.
•
More on inheritance next week.
• Public:
• Everyone can access a public member or method.
• Concept of least privilege: don’t allow any more access than you need to.
• Note to C++ programmers: Java doesn’t have “friend” classes.
Encapsulation
• Classes should stand on their own as much as
possible.
• They do this by hiding details of their
implementation (using private) and providing
access to the class through public methods.
– This restricts the actions the caller can take on
objects of your class to the methods you provide.
– This is a good thing because you gain more control
over how your code is called.
Static Members
• Both variables and methods can be static.
• Normal member variables belong to an object.
– 1 object, 1 instance of the member.
– Two “Employee” objects would have different names and salaries, for
example.
• Static members belong to the class itself.
– 1 instance no matter how many objects.
• You can invoke static members using the name of the class, without
creating an object:
– For example: Math.random() is static.
– So is main!
• Because static methods are not associated with a particular object,
they can only access other static members on their own.
– But you can declare objects of your class and access their members.
Back to the Game
public class Guesser {
public static final int MAXNUM = 100;
private final int secret;
This class is encapsulated. There is no way for you, the
caller, to find out the secret other than to guess it.
//Generate the secret number in the constructor.
public Guesser() { secret = (int) (Math.random() * MAXNUM + 1); }
//Returns < if the number is less than the guess, > if greater, = if equal.
//This uses the “ternary operator” – which is just a concise way to write if/else statements.
public char guessNumber(int guess) { return (secret > guess) ? ‘>’ : ((secret < guess) ? ‘<’ : ‘=’); }
}
We already know the algorithm: find the midway point, guess, change the
boundaries of the acceptable answers depending on whether the guess was
low or high. Can you think of some code that would do it?
Analysis
• When you used this strategy manually, it took
logarithmic time. Let’s take a look at the code
to see whether this is still true.
All fun and games this time…
•
•
My original plan ended here, but we kept going.
The lesson:
– The principles of Java owe an intellectual heritage to C++. Much of “progress” is successive
copying with some changes. Your existing knowledge will be useful to you when learning new
techniques.
•
Next class: Searching, basic sorting, sorted arrays, and intro. to recursion.
•
Assignment 1: Design an automatic guessing game.
•
•
•
•
•
•
•
Due Thursday, 9/11.
Rather than having the user guess the number, have the program try to guess it according to
the strategy we discussed.
Keep track of the number of guesses required. Run the program several times and report the
average and worst number of guesses. Does this agree with our worst-case assumption of
log(n)? (The base-2 log of 100 is 6.64. There’s no such thing as .64 of a guess, so round to 7).
Try varying the maximum number the program will choose up to. How do the average and
worst number of guesses increase with the input? Do they increase logarithmically?
Remember, in CS, logarithms are base 2. To do base 2 logs on a calculator, use log(x) / log(2).
You may use the Guesser class that I provided.
Contact me with any questions.
Arrays
•
•
•
Reminder: Data structures are models that make certain types of access to your
data easier.
Among the simplest of these models is the array.
Arrays are contiguous homogenously typed addressable collections of data.
– Contiguous: Element 2 immediately succeeds Element 1 in memory.
– Homogenous: Every element is of the same data type.
– Addressable: You can access an individual item in an array based on its index.
•
RAM is actually just one very big array.
– Memory addresses are indices into the array.
•
Both C and Java have built-in support for arrays.
– You’ve seen at least one: String[] args in main.
– Arrays in C are just pointers. Java gives you much more.
•
When you declare an array in Java, the object gets the size.
– Example:
•
Employee[] e = new Employee[10];
Accessing an array is simple:
– System.out.println(e[0]);
– The index runs from 0 to size-1.
•
The most fundamental difference between arrays in C and Java:
– You can get the size:
System.out.println(e.length);
//Prints 10.
An Array
Data
10
21
44
-13
7
26
28
14
Index
0
1
2
3
4
5
6
7
Contiguous: adjacent elements are adjacent in memory.
Homogenous: all elements are “int”s.
Size: 8.
A[0] = 10
A[4] = 7
A[8] will throw an ArrayIndexOutOfBounds exception in Java.
Random Access
• CRUD operations: Let’s start with reading.
• Reading an array is easy: just use arr[index].
– This is a constant-time (O(1)) operation, no matter what
the index is.
– This is possible due to the contiguous and homogenous
properties of the array.
• All elements are the same type.
• All elements are adjacent in memory.
• All Java needs to do is offset sizeof(type) * index from the start of
the array in memory – quick lookup.
– This is known as “random access”.
• Because looking up a random element always takes O(1).
• And this is why RAM is called “random access memory”.
Insertion on Unsorted Arrays
• Since we don’t care about the order, we can
insert at the end.
– If we wanted to insert in the middle, we’d need to
shift everything after it down – O(n).
• This is simple: keep a counter of how full the
array is and increment it as we go.
• Let’s call it arrcount and initialize it to 0.
• We can just say: arr[arrcount++] = newelem;
• Since arr[arrcount] is O(1), so is insertion.
Updating
• arr[index] = newval;
• Simple, easy, also O(1) due to random access.
Deletion
• Two interpretations:
– The book’s: You need to shift everything beyond
the target element down.
– Mine: If the order really doesn’t matter, you can
just swap with the last element and decrement
the counter you’re using to keep track of the size.
– “Shift everything down” is linear – you may have
to move up to n-1 items.
– The swap method is constant-time.
Unsorted arrays seem pretty good.
•
•
•
•
•
•
Insertion at end:
Insertion in the middle:
Accessing any element:
Updating an element:
Deletion (shift):
Deletion (swap):
O(1).
O(N).
O(1).
O(1).
O(N).
O(1).
• Why use anything else?
– Using only arrays worked pretty well in VB.
– We could end the course now!
Back to reality…
• There are some drawbacks, however:
– If you don’t know how large the array is, you’ll have to do
one of three things (all of which trade off):
• Underestimate and tell the user he’s out of space (flexibility).
• Overestimate and waste space (space).
• Grow the array dynamically as it gets larger (time + complexity).
– Searching for an element in the array is linear.
• Access and Search are generally the most
frequent/important actions a program will take.
– Unless you’re doing a lot of writing; e.g., logging data.
– These are the ones we want to optimize, then.
Growing the Array
•
•
•
•
Idea: when the array runs out of space, make it bigger.
Problem: you can’t resize arrays.
Solution: create a new, larger array and copy.
Double the current size is usually a good choice.
– The overall number of doubles you’ll need to do for n insertions
is O(log n).
• The algorithm:
– Create a new array of size n*2: O(1).
– Copy the data to the new array: O(n).
– Refer the variable to the new array: O(1).
• There is a very useful Java class that will do this for you.
– Look up the Vector class in the Java API.
– We’ll cover these so-called “container classes” later on.
Growing the Array
A=
B=
A
Data
10
21
44
-13
Index
0
1
2
3
Data
10
21
44
-13
7
26
28
14
Index
0
1
2
3
4
5
6
7
Linear Search
• What’s the problem with searching an
unsorted array?
Worst case: Find 15.
Found it?
Data
10
21
44
-13
7
26
28
14
Index
0
1
2
3
4
5
6
7
• We have to search every element: O(n).
No.
Linear search: The Algorithm.
• You should be able to figure this one out.
• It’s very intuitive.
Object[] arr;
for (int i = 0; i < arr.length; i++) {
if (arr[i].equals(target))
return i;
}
return -1;
//“Sentinel” value; not found.
Binary Search: A Better Way
• If you know the array is sorted, it’s possible to
search it in O(log n) time.
• This works using the same principle as the
guessing game:
– Eliminate half of the array on each try.
• There are some tradeoffs to sorting the array.
– See what I mean? Tradeoffs are everywhere!
• We’ll discuss this more next week.
Fin.
•
•
This is really the end. To re-post slide #14:
The lesson:
– The principles of Java owe an intellectual heritage to C++. Much of “progress” is successive
copying with some changes. Your existing knowledge will be useful to you when learning new
techniques.
•
Next class: Searching, basic sorting, sorted arrays, and intro. to recursion.
•
Assignment 1: Design an automatic guessing game.
•
•
•
•
•
•
•
Due Thursday, 9/11.
Rather than having the user guess the number, have the program try to guess it according to
the strategy we discussed.
Keep track of the number of guesses required. Run the program several times and report the
average and worst number of guesses. Does this agree with our worst-case assumption of
log(n)? (The base-2 log of 100 is 6.64. There’s no such thing as .64 of a guess, so round to 7).
Try varying the maximum number the program will choose up to. How do the average and
worst number of guesses increase with the input? Do they increase logarithmically?
Remember, in CS, logarithms are base 2. To do base 2 logs on a calculator, use log(x) / log(2).
You may use the Guesser class that I provided.
Contact me with any questions.