TOMMY MACWILLIAM: In this video, we're going to write our first Android app.
To get started we're going to be using an app called Android Studio to write
all of our Android code.
Android Studio is an IDE, or an Integrated Development Environment,
that's provided by Google to help you write Android apps.
So let's take a look at Android Studio and create our first app.
So I'm going to open up Android Studio.
And now to get started, I'm going to come over here and select
Start a New Android Studio Project.
Now here I have a bunch of different options here.
Our app is going to be pretty simple, so I'm just
going to select this third one over here, this Empty Activity.
Then I'm going to click Next.
And then it's going to ask me just some information about my project.
So first I'll give it a name.
I'm just going to call this JavaExample.
And then it's going to ask you a few questions about where
to save your project.
I'm just going to put mine on the desktop for now.
For package name you can select whatever you want here.
A common convention when writing Android and Java code
is to take some domain name you own and have the package be that domain name
reversed.
So CS50's home page is cs50.harvard.edu, so I've selected edu.harvard.cs50
as my package name.
And then the end here, this javaexample, is just a lowercase version
of the project name that I selected.
For language we're going to select Java.
And lastly, this minimum API level.
This basically says, what is the lowest version of Android
you want your app to support?
And you can see here that as I change different versions
the IDE will tell me approximately what percent of devices
out there that we're going to support.
So for these videos we're just going to be using Android 5.0, which
is pretty widely supported.
But it's up to you what minimum version you want to support.
And we have a couple other questions here.
One is about supporting instant apps.
We're not going to worry about that.
And this last checkbox is about using AndroidX.
And so this is basically just a newer version of Android libraries.
So we're going to check this, since that's sort of the new version
that we want to use.
After that we'll click Finish.
And here we go.
So now we're inside Android Studio.
And you can see that we actually generated a bunch of files for us.
And so we'll go through those in a bit.
Before we do, we first need to create an AVD, or an Android Virtual Device.
So this will basically allow you to run Android apps on your laptop
rather than needing to plug in an Android device.
So to create an AVD, what we're going to do
is we're going to go through Android Studio,
we're going to specify what type of device we'd like to simulate,
as well as what version of Android is installed, and so on.
And then once we've created that, we're going
to be able to run apps on that device.
So let's go through and create an AVD now.
So to create an AVD inside of Android Studio, I'm going to come up here.
And in the top right, you'll see this little Android logo and a phone.
And it says AVD Manager when I hover over it.
So I'm going to click that.
And you see here that I already have a couple of virtual devices created.
But just to walk you through creating one, down on the bottom right here,
you'll see a button that says Create Virtual Device.
So I'll click that.
And I'll have this pop-up appear.
And here you can see a bunch of different types of phones.
So for example, if I wanted to emulate a Pixel 3a, I can click on that.
Then I'll click Next.
And then here it's going to ask you what version of Android
you want to put on that phone.
So, up to you which version you want to use.
I try to use a recent version.
So I already have Android 9 downloaded.
But if I didn't have Android 8 downloaded,
I could just click on Download here.
After you click Next, you have a few different options here
around just some other sort of graphics options and some advanced stuff.
You don't really have to worry about that.
You can just click Finish to create your AVD.
So before we get started writing any Android code,
let's walk through a little bit of the syntax of the programming language
that we'll be using to write Android apps.
So we're going to be using Java when writing our Android apps.
Google also supports this programming language called Kotlin.
That's pretty similar to Java.
But throughout these videos we'll just be using Java.
So Java is a little similar to C. It has some differences but also
a lot of similarities.
Let's start by first looking at all of these data types available in Java.
Some of these probably look really familiar.
Much like in C, Java has int and char, double, float.
All that stuff you're familiar with is supported in Java.
And Java also has a whole lot of more advanced data types like list and map
that we'll get into in a bit.
But the Java standard library, or the sort of set of objects and APIs
and libraries that's provided to you by using Java, is really, really large.
And so we won't go through everything in these videos,
but we'll try to touch on some classes that you'll really
commonly use while writing apps.
So here's our first few lines of Java code.
And here we're just going to initialize a few variables.
And this should look really familiar.
In this first line here we're creating a new variable.
Its type is a String.
Notice that in Java that's capitalized.
And then we have an equal sign, and the right-hand side
is just the value of that string.
Then the next line, we're creating an int, setting its value equal to 50.
And then we can change that value using the same exact syntax that you
used in C. Also notice that every line ends with a semicolon, something
you're also used to from C.
Conditions look pretty much the same.
We can create another string variable.
In this first line here, notice how I'm not using a double equal sign here.
I'm saying title.equals().
So we'll get into this a bit later.
But this is something that's called a method on the String object.
So rather than saying equals equals whenever you're comparing strings,
you'll have to remember to say .equals(),
or else you won't actually get the right comparison.
On the third line here this is equivalent to printf in C.
This is how I would print something out to the screen.
I can say System.out.println, and that's going
to print something to standard out.
Else works sort of the same way that you're used to in C.
Next up are arrays.
Again, pretty similar to C. In this first line here
I'm declaring an integer array called values.
And then on the right-hand side, this is where
I'm assigning an initial list of values to that array.
So to do that in Java, I'll say new followed by int--
that's the type of the array again--
and then in braces 1, 2, 3.
So this syntax, a little bit different than what you're used to seeing.
And then in the next few lines I'm going to be iterating through that array.
So unlike in C, Java arrays know how large they are.
So I can just say values.length in order to get the length of this array.
So there's sort of no need for me to pass that in separately.
With any array I can always get its length.
And then the rest of this for loop should look pretty familiar.
I'm creating a variable to start that I'm going to use as my counter variable
to step through that array.
I want to keep looping until that counter variable is less
than the length of my array, because remember, arrays are zero-indexed.
They start at 0, not 1.
And then at the end of each loop I just want to increment that counter variable
so its value is one more than it was on the previous iteration.
So hopefully all this looks pretty familiar at this point.
Java also supports something called lists.
And you can think of a list as basically a dynamically sized array.
So with arrays, once you initialize them with some values,
it's really hard to add on one or remove a value.
With lists it's actually really easy to add and remove values.
So in this first line, this is the syntax for creating a list.
So we're first saying my type is List.
And then you'll in angle brackets here, we're
going to specify the type of the element inside of the list.
So this is a list of strings.
So I have List, and then in brackets String, which is just the type.
Then my list is called values.
And then I'm going to be creating a new instance of a list.
So that's why I have this new operator.
And the type of list I want to create is an ArrayList.
Java supports a few different types of lists.
ArrayLists is the simplest, and so we're just going to use that.
Then in these next two lines I'm going to be adding an element to that list.
I can say values.add("one"), values.add("two").
And after those two lines execute, I now have
a list of strings with two elements.
So you can see I'm dynamically adding element to that list.
Then to iterate over that list this, this is called a for-in operator.
Basically it's just a shorthand for that for i equals zero,
i is less than i++ syntax we just saw.
I can say for String value, followed by a colon, and then the name of the list
I want to iterate over.
So by saying String value colon values, I'm basically saying,
I want to iterate over every element in this values array.
And then what I want to do at that value is just print it out.
So I can say System.out.println, and that's going to print the value.
So just to dive in a little deeper on that syntax,
we saw that using that angle bracket, we're
specifying the type that's contained within the list.
In Java this is called a generic.
And it's basically a way for one class or one type
to understand something about what's inside of it.
So you can basically pass a type to some other type.
So for example, if I wanted to create a list of integers
rather than saying capital String, I would just say capital Integer,
and then I can add integers to that list in the same way.
Java also supports a data type called a map.
In other languages this might be called a dictionary,
or in JavaScript an object.
And the syntax is pretty similar.
You can think about a map as, rather than just
being a list of values, a mapping from some key to some other value.
Much like a dictionary maps words to definitions, our Java map
is going to be kind of the same concept.
So in this first line we're creating a map.
And this time inside of my angle brackets
I'm specifying two things instead of one.
And that's because we need to give both the key and the value.
So by saying map string comma string, I'm saying,
I want to create a map that maps strings to strings.
Then the right-hand side, I'm saying new HashMap.
And again, Java has a few different types of maps.
HashMap is probably the simplest so we're just going to use that.
And then notice inside of those brackets on the right-hand side,
I don't have anything.
If I wanted to, I could technically repeat string comma string there.
But the Java compiler can understand, because I
said string comma string on the left, I don't
need to say it again on the right.
So it's just sort of a shorthand.
These next two lines are how I might insert something into that map.
So I can say airports.put().
And then I'm creating this mapping between airport codes
and the name of the airport.
So I'm creating a new entry with a key of "SFO"
and a value of "San Francisco."
Similarly I can create a key of "BOS" and a value of "Boston."
Then to iterate through that map, and say
I want to get everything inside of that map
and understand what the keys and values are, I can use that same for-in syntax.
So I'm going to say for.
And then the type of the object I'm going to use to iterate
is going to be a Map.Entry.
So again, this is just saying, I want to get
a pair of key and value-- sort of a key and its corresponding value.
And to do that, I'm going to say airports.entrySet().
And that's just going to give me a list of those pairs.
So once I have that list it's really easy.
I could just say .getKey() or .getValue().
And those are going to do exactly what you'd expect--
either get the key or the value for each entry in that map.
So if I were to run this code, what this would do is this would print out first,
"SFO" followed by a colon followed by "San Francisco."
That would be the first iteration of the for loop.
Then the second iteration of the for loop would be "BOS" colon "Boston."
So basically, just walk through that map,
and we can do whatever we want with each key and value.
So list and map are actually something called classes in Java.
And when we're writing Java, we're going to be writing a lot of our own classes.
You can think about a class as basically a struct that
can also have functions attached to it.
And when we write a function inside of a class,
we're going to call that a method.
So here's the syntax for creating a class in Java.
So we're going to start by saying public class.
This "public" says that other classes inside of your application
can also use this class.
You might also say something like private class
if you wanted to say, this class is private,
I don't want any other classes in my application to use it.
But public is a reasonable default. Then class, then the name of your class.
So here we're creating a class called Person.
Notice that the class is uppercase, just like list and map were.
And that's just sort of a Java convention to start all of your classes
with an upper case letter.
Then we'll use an open brace to start the class.
Now, this class has one field.
And this field is of type String.
And we're calling it name.
Last, we're going to create what's called a constructor for the class.
And a constructor is basically a special method
that's going to be called when you create a new instance of that class.
So here my constructor takes one parameter.
It's a parameter of type String, and we called it name.
And all my body does is take the parameter that's passed in by the user
and save it.
So that way, later on in other methods of the class
it can use whatever the user passed in to start.
So by saying this.name equals name, I'm saying,
I want this name field that I declared on the second line
here, I want the value of that to be equal to whatever the user passed in.
And now to use my class, we can look at this last line
here, where is starts with the type.
My type now is Person.
I basically defined a new type by creating that class.
The name of that class is person now, but with a lowercase letter,
since again, it's just sort of a convention
that objects or instances of a class will
start with lowercase letters and the classes
themselves will start with uppercase.
Then I'm saying I want to create a new, and then Person again.
And by passing in "Tommy," I'm going to invoke this constructor
with the value "Tommy."
So I mentioned that classes can also have methods.
And so here's an example of that.
Let's say that we still have that constructor in that field name,
just as before.
And now I'm going to declare a method on this class.
So we're starting by saying public.
Again, that's so that other classes using
an instance of this class or an object can call this method.
Next is the return type of the method.
It's just void, which means we're not going to return anything.
And then the name of the method.
So here you'll notice this is also camel case,
so starting with a lowercase letter, and then every new word
will start with an uppercase letter.
This method doesn't take any parameters.
And its body is just one line.
We're just, again, going to print something out to the screen.
And we're going to say, "I'm" and then that name variable.
So you'll notice here that we don't need to pass in again that name
variable to this method, because we already passed it to the constructor,
and then we saved it.
So by just saying name here, Java knows that this name actually
refers to that name field inside of your class.
So now, to use this method I can create that person just like before--
say new Person, pass in some value.
And then I can say person.sayHello().
And that's going to call this method.
So this is just like before when we were looking at lists and maps.
When you said airports.put(), put() is just a method on some map class
somewhere.
And we didn't write that map class ourselves.
Someone else wrote that and provided it to us.
But under the hood that's basically what's happening here.
We could also have what are called static methods.
And these are methods that you can call on a class
without having an instance of it.
So instead of saying public void wave, I've
just said public static void wave here.
We can define the method in the same way.
The body of the method is just like any other method.
But then to call this method, on this last line here you can see I'm saying,
capital Person-- so that refers to the class--
.wave().
So here we didn't have an instance of that class.
We're not using an object.
We're just referencing the class itself, and we're calling wave.
And this can be helpful if there's any methods that you
have in a class where it doesn't really make sense to instantiate a class,
or it's just sort of unnecessary to have an object around.
And that's where a static method might come in handy.
One of the more powerful features of classes is inheritance.
And inheritance allows you to say, I have
some base class or some parent class that
defined some fields and some methods.
And I want to take that class and modify it a little bit.
So maybe I have some other class I need to write
that's really similar to that first one, but I
want to change some of the behaviors in this new version
and keep some of the other ones.
So let's walk through an example.
Here we have a class called Vehicle.
And this Vehicle class has two methods.
This first method you can see it returns an integer.
I've just called it wheels(), and it returns 4.
And this says, OK, for every vehicle, it has four wheels.
Then I have another method called go().
That's just going to print something out to the screen and not return anything.
So nothing new here.
This is just a regular class, and we can instantiate that class
or create an object in the same way, and call these methods in the same way.
But let's say now that I'm writing a class to represent a motorcycle.
And a motorcycle is basically a subclass of a vehicle.
You can think of a motorcycle as a type of vehicle,
meaning it shares many of the same properties,
but some things are a little different.
So to capture that, I'm going to start declaring my class in the same way.
I'm going to say public class Motorcycle.
And then I'm going to say extends Vehicle.
So this in Java is how you're saying this class
inherits from this other parent class or superclass.
And after I say extends Vehicle, now my Motorcycle class
has access to everything that was in that Vehicle class.
So I could say Motorcycle.wheels() and get back 4, Motorcycle.go(),
and it would print out something to the screen, just as I could with Vehicle.
But now what I want to do is override that wheels function.
Because motorcycles have two wheels and not four.
And so to do that, I'm just going to basically re-declare this wheels()
method.
I'm going to say public int wheels().
And then rather than returning 4, I'm going to return 2.
And you'll notice on this second line I've also
added what's called an annotation.
It says @Override.
This is basically just a signal to the compiler
telling the compiler that I just overrided this method.
If I forget the override, that's OK.
But it's really helpful, because if I had this @Override,
and I tried to override a method that didn't
exist, the compiler would tell me, hey, you're
not actually overriding anything.
You probably messed up somewhere.
So whenever you're overriding a method it's
really helpful just to add this @Override before you do that.
So that's extending classes.
And in Java you can also have something called an interface.
And you can think of an interface as basically a list of methods
that some class has to implement.
And if they don't implement all of the methods
in some interface, the compiler will tell you, hey,
you have an invalid class here.
You're not implementing one of these methods
that you told me that you were going to implement.
So here's an example.
So we'll start our interface with public interface.
And we're going to name this Teacher.
And now, inside of this interface we just
have one method which has a void type.
It's called teach().
But what's interesting about this is there's no method body here.
We haven't specified at all what it means to teach.
We've just said, in order to be a teacher, you have to know how to teach.
It's basically the same as signing some contract,
saying, if you're going to use this interface,
you promise that you're going to implement this method for me.
So now, to use this interface it's pretty similar.
We can say public class CS50Teacher implements Teacher.
And this says, there's some interface.
I'm implementing every method inside of that interface.
And a class can implement as many interfaces as it wants.
I could have said Teacher comma and then some other interface.
But we can only ever extend one class.
So in Java you'll see really commonly lots of interfaces,
and classes can conform or implement a bunch.
But when you have a base class or superclass,
you can only have one per class.
Now, to implement this interface, same as before.
We're just going to declare a method in our class
with the same name and the same type as that interface.
So I'm going to say, @Override, just to make sure the compiler would tell me
if I'm overriding it incorrectly, public void teach().
And then this method is probably a little complicated to implement,
so we're not going to worry about that right now.
So now let's return to that line we had before,
where we created a new list of strings.
And hopefully this is going to make a little more sense now.
On the left List is actually an interface.
So we want to say that the type is something
that conforms to the List interface or implements everything
inside of the List interface.
These brackets, remember, are a generic.
It's a way of telling the List interface or this instance of a class,
I want you to know that you're going to contain strings.
And String is a class.
And so we're passing on that class to this other one.
And then the right-hand side, this new ArrayList,
this is actually a class somewhere that implements List.
So that's why the left and the right-hand side are different.
The left-hand side is basically a more general thing saying,
some type of list-- it could be anything.
But as long as it implements a list, we're
OK, because we're only going to be using methods
that are defined in the List interface.
And then the right-hand side, ArrayList is a concrete class
that implements the List interface.
If I wanted to, I could have said ArrayList strings equals new ArrayList.
But by convention you want to use the type that's sort of the most general
and makes the most sense, because you might not want to use an ArrayList.
It might be something else under the hood.
And so you're kind of abstracting away or hiding that detail under the hood
by just saying, I'm only using these methods in a list.
As long as this class has those, it doesn't really matter to me
under the hood what type of list it is.
Java also has this notion of packages.
And that's something we're going to see pretty quickly.
But this basically provides you a way to namespace your class.
So often in a Java application you're going
to have a bunch of different classes spread apart
a bunch of different files.
And packages basically provide you a way of organizing those.
So you might want to do something like, if your app has two screens, put
all of the classes used in one screen inside of one package,
use all the classes contained in another screen inside of another package.
And that way you can sort of more cleanly organize your code.
Sort of equivalent to using folders to organize your files in your computer,
we can more logically organize things instead
of just having a list of 100 classes all sort of at the same level.
So that's package.
And then to use a package, we're going to use this import statement.
So to actually use those List and Map classes in a real application,
I'd first have to import them.
And that's just telling the compiler, I need to use a List class somewhere,
and here is where you can find the definition of that List class.
So List, for example, is located in the package java,
which means it's the Java standard library-- we didn't write any of this,
it's just given to us because we're using Java--
.util-- which means there's a package somewhere called util,
which is short for utility--
and then the class name, and it's .List.
That's the name of the class that we want to use.
So once in my file I've added this import java.util.List,
that's going to mean I can use this List class-- or this List interface,
actually-- wherever I need to inside of my code.
So that's a whole bunch of syntax.
But we've basically covered everything we're
going to need to start writing some Android apps.
So now let's take a look at an example.
Let's return to Android Studio and start writing some Java code of our own.
Over here on the left is all of the files contained inside of my project.
And we'll go through these in a bit.
You can see there's a few folders.
The folder we care about right now is a folder called java.
And that's where all of our Java code is going to live.
Then here you can see the package that we created.
So remember, we called that edu.harvard.cs50.javaexample.
That's our package name.
And you can see here that the file that was generated for us
happens to start with that package.
So hopefully that makes sense now.
And then the class that we've created is called MainActivity.
It looks like it extends some other base class called AppCompatActivity.
If I come over here to this import line and click the plus,
we can see that, OK, it looks like we've already
imported this class from somewhere, in particular that AndroidX package which,
remember, is a bunch of support libraries
that we can use to build our application.
And then it looks like we have some method here
that's already defined for us.
It's overriding some method in the base class.
It has that @Override.
The visibility is protected.
And this means something basically between public and private.
This means that if I subclass this class that those subclasses can access this
method, but other classes can't.
Its return type is void.
The method name is onCreate().
And it takes one parameter.
The parameter has a type Bundle which, from the looks of it,
is something that's also provided to us from Android, since it's
being imported up here.
And the name of this parameter is savedInstanceState.
OK.
So in this next line we're going to be calling the method onCreate()
that's defined in AppCompatActivity.
And this is a really common pattern when you subclass something.
Oftentimes when you're overriding a method,
you don't want to override it completely,
because maybe that method was doing something important.
In this case the method in AppCompatActivity probably
is doing something important.
So you also want to use that definition.
So by saying super.onCreate(), I'm saying,
I want the method that's defined in AppCompatActivity,
and I want to call that before I override it and do something of my own.
So by doing that we're making sure that, not only are we provided by our own
definition for onCreate(), we're also taking advantage of whatever
AppCompatActivity has defined.
So we're passing it that one argument, just savedInstanceState.
And lastly, it looks like we're just calling some other method
that's defined on AppCompatActivity called setContentView().
And let's not worry about this right now.
We'll get into that a bit later.
But here is where we can start writing some Java code.
And the first Java code that we're going to write
is it really simple sorting hat application.
So in CS50 we have a few different tracks here.
We have one for games, one for web, and one for mobile.
And so we're going to write a really simple app
that just randomly sorts students into one of those tracks.
So let's get started.
The first thing we want to do is create a class to represent a track.
So let's do that.
Let's come back over here to the left.
And I'm going to Control-Click on this package name.
And I'll see this long menu.
But what I care about is creating a new Java Class.
So let's click that.
And they have this nice menu here.
It's going to ask me a few things.
First is the name of the class.
I'm going to call it Track, because I'm creating a new track.
It's just going to be a regular class.
It's not extending anything, it's not implementing any interfaces.
You can say its default visibility is public.
Don't have any modifiers.
We're not worried about that right now.
And the package we want to add that to is just the same package.
No need to create anything else here.
So let's click OK.
And there we go.
So Android Studio has nicely generated this class for me.
And if I come back over here to the left,
we can see that it's inside of that same package as this other class
called MainActivity.
So let's see.
We want each class to have a couple of fields.
Let's call one of the fields a public String name.
And this will represent the name of a track.
And let's call the other field the instructor.
And that's going to be the instructor for the track.
So after creating these two fields, let's now create a constructor.
So remember, the constructor is just going to be the same name as the class.
And you'll notice Android Studio has this really nice autocomplete.
That's something you should definitely take advantage of while you're coding.
So as I started typing "Track," Android Studio recognized,
hey, we've got a class called Track.
Maybe you meant to type that.
So if I just hit Enter, it's going to autocomplete for me.
So now let's add those two parameters-- one called
name, one called instructor-- again, autocomplete being helpful here.
And all we want to do is save those two things.
So we can say, this.name is name, and this.instructor is instructor.
Using autocomplete you can look like you're typing really fast
and impress your friends.
So that's it for this class.
We're not going to put any methods on this quite yet.
We're just going to save.
It's basically a container for these two data types.
So now let's come back to MainActivity.
The first thing we want to do is create a list of tracks.
So let's do that.
Let's say we have a new List.
Again, Java being helpful here, in this autocomplete,
if I just press Enter we're going to have something really cool happen,
which is that Android Studio automatically added that import for me.
So when I hit Enter, not only did it type the word List,
it also added this import to the top of my file saying, import java.util.List.
And again, that import is necessary for me to use this class.
So Android Studio is just being helpful with that.
OK.
So we have a list.
Remember, the type of our list is a track, because it's a list of tracks.
That sounds good.
Let's call our variable tracks.
And then same as before, let's just create a new ArrayList.
So we'll say new ArrayList.
If I hit Enter, notice that it's imported automatically.
And that's it.
We don't have to specify the type again in the right-hand side.
We can just do this left right bracket thing.
OK.
So now let's add some tracks to this list.
So remember, we're just going to say tracks.add.
And then we want to create a new track that takes two parameters.
The first one is the name of the track.
And again, Android Studio is just being a little helpful
here by putting in that name prefix.
This actually isn't part of the source code.
This is just something that's displayed in the IDE.
But it's helpful just to remind you what those variable names were called.
So let's create the mobile track.
The instructor is Tommy.
Again, being helpful with these parameter names.
But this is not really part of your source code.
You don't need to type name colon anywhere.
So that's our first track.
Our second track is the web track.
And that's with Brian.
And the final track is the games track.
And that's with Colton.
OK.
So at this point we've now created a class to represent each track,
we've created a list of those tracks, and then
we've added these three instances of those tracks to that list.
That looks good.
So now let's create a list of students.
So rather than saying Track here, I'm going
to say String, since we'll just represent each class as a string.
And you'll notice here that I don't need to import String.
That's actually imported for me automatically.
There's a package in Java called java.lang.
And everything in that package is automatically imported.
So no need to import that manually.
So then we'll call them students.
And again, let's just sort of add some strings here.
We could say new ArrayList.
But there's also a nice shorthand I can use in Java
rather than saying new ArrayList add, add, add.
I can use this other class called Arrays.
It's also in java.util, imported automatically.
And there's this method on the Arrays class called asList().
And this is an example of a static method.
Notice that I didn't say new Arrays anywhere.
Arrays is just the class itself, and now I'm calling the static method.
And now I can just actually put in a list of strings.
So I can say--
let's just pick three totally random normal names
like Harry, Ron, and Hermione.
And there we go.
So this is actually going to give me back a list of strings.
So now we want to do two things.
The first thing we want to do is randomly assign students to tracks.
And then after that we want to print out the resulting assignments.
So to do that assignment, we're going to use a map.
And this map is going to map strings, which represent students, to tracks.
So let's declare that map.
So we're going to say Map, imported automatically.
And remember, this time we need to specify two different types.
The first type is the type of our key, which is a string.
And the second type is the type of the value, which is a track.
So we'll call this map assignments.
And then we'll say new HashMap.
Again, Map is the interface here, HashMap is the class.
Don't need to specify anything on the right-hand side.
All right.
So now we have this map.
It's empty, so let's put something in it.
So to do that, we're almost surely going to need
to iterate through all of the students.
So let's use a for loop for that and say, for String student in students--
so now that's just going to walk through that list one by one.
And so what I want to do with each student is,
I want to figure out how to get a random track.
So luckily Java, again, has a nice class that's part of the standard library
that we can use.
And that class is called Random, also located in java.util.
I can just say Random, let's just call this object random.
And it's going to be a new instance of the Random class.
Constructor doesn't take any arguments, so we can just say that.
And now to generate that random number, I can just say,
my index is going to be random.nextInt()--
again, autocomplete helping me out here.
And this is going to take one argument.
And this argument is going to be the maximum random number
that you can generate.
And so that's just going to be the size of my list.
So with the List object, I can just say .size().
That's a method that's defined on List that
will give me back an integer value representing how many students are
in the list.
So now that we have this index, let's use it to get one of our tracks.
So I'm going to say assignments.put, just like before.
And autocomplete here again, reminding me
it's going to take two arguments, a key and to value.
My key is going to be a string.
And that's the current student that I'm iterating.
And the value is going to be one of the tracks.
So to get value out of this ArrayList, I'm
going to say tracks.get, pass in that index.
And that's going to get me an object out of that array.
So notice here that in arrays you can use that square bracket notation.
The ArrayList is just a regular class that has methods defined on it,
and get() is a method.
You'll oftentimes when writing code, much more frequently used
lists and maps compared to raw arrays.
But they're there if you need them.
OK.
So at this point in our code we have defined a list of tracks,
we've assigned students to those tracks.
And now we just want to print everything out to see what the result is.
So to do that, we're going to use another for loop,
this time iterating over the map.
So we're going to say for.
Again, we have Map.Entry.
And this is basically a class defined within the Map class
that represents a single pair of key and values inside of the map.
The type of this is going to be the same.
It's going to be mapping a string to a track.
We'll just call this Entry entry.
And then we can say assignments.entrySet.
So this entrySet is going to return a set, which is very similar to a list.
It just says that everything in this list is unique.
But for all our purposes it's just a list.
And so now that I have this entry, I just
want to print it out to the screen.
So when you're writing Java code, we saw before we have that System.out.println.
And that's a way to just print to standard out.
When you're debugging Android code in Android Studio,
there's another class you can use called Log.
And Log is basically going to allow you to print
to the special area in Android Studio.
You can search over logs and navigate them a bit more easily.
So we're going to use that.
So we're going to say Log.
It's this class defined in android.util.
And then there's a bunch of methods to find on this object.
And a bunch of them have a single letter.
So there is e() for error, there is d() for debug, there's i() for info--
that basically just says what level what we logging at.
So like, are we making a debug print statement,
does this log represent an error statement?
It doesn't matter too much.
We're just going to use d() for debug.
And we see here that this method takes two arguments-- a tag and a message.
So the tag is a way for you to really easily filter down messages.
So when we launch our Android app, you're to see that a bunch of stuff
is going to be logged.
And much of it is going to be from the system
or from other libraries we're using.
And so we want to easily find our log statements
among all of those other ones.
So if we just create a tag of cs50, that's
going to allow us to search for cs50 and easily find our log statement.
So that's our tag.
And then we want to print out this entry.
And if I call the getKey() method, that's going to give me the student.
So that's the student name.
We can concatenate strings together with plus.
So we can say this "student got."
And now we can say entry.getValue().name.
So this is going to be the name of our track.
And then I can say "with" followed by the name of the instructor,
which would be entry.getValue().instructor.
And I forgot a plus, so I'll add that over there.
OK.
So now let's run our app using the AVD we created earlier to simulate
this Android app.
So up in the top right here you'll see this Play button.
So I can just click this, or as it tells me,
the keyboard shortcut is just Control-R. So let's click that Play button,
which is going to open up our Android emulator.
So here's my emulator.
You can see this Android app was sort of automatically generated for us.
But we're looking for that log output to see what our assignments were.
So if we come down to the bottom here, we
have this thing here that says Logcat.
And this is basically just all of the logs coming in from our application.
So you can see here there's a bunch of stuff being logged by the system.
But if you scroll up, then you can see our assignment here,
which just so happens to be one person in every class.
And this is the result of our log.
So before we finish, let's change one thing about our class.
Rather than exposing these fields as public fields,
a pretty common convention in Java is to provide what
are called getter and setter methods.
So to do that, I'm going to define methods on this track called public
String getName().
All this is going to do is return the name.
And another getter called getInstructor().
And that's just going to return the instructor.
And so now, rather than exposing these fields publicly,
I can instead make them private, which says
that you can't just access these fields, because they're marked as private.
Instead you want to use the getters.
This is a pretty common Java convention, because you might
want to do something inside the getter.
You might have a convention where getting the value of something
isn't just the value, it's that value, maybe it's modified a little bit,
maybe it's doing some calculation on that value.
So you don't really want to expose these fields directly.
It's common to put them behind getters.
And you'll notice in a lot of the code that we've written so far we've already
used getters, like getKey() and getValue().
So we're just following that same convention.
So now to modify the code that we have here, let's shorten this a bit.
And let's say that we have a Track track.
And that's going to be equal to entry.getValue().
So now we have a Track object.
And now we can say track.getName(), use that method we just defined,
and track.getInstructor().
You'll notice it if I try to use just track.instructor,
the compiler is going to let me know that I have an error.
You'll see here it's highlighted in red.
And I have this little message that says,
instructor has private access in this class,
which means I can't access it from outside of the class.
So by just saying getInstructor(), now we should be good to go.
Let's run our app one more time.
So we're launching.
And you'll notice all the log is cleared.
And if we just scroll up again, we can see a new random result.
And by the way, this search bar is pretty nice up here.
So I could, for example, search "Tommy."
And I'm going to filter down only the log messages with "Tommy."
So I could say "with" and only get the messages with "with."
So for example, if I changed this tag just from "cs50" to something
like "assignment result," I could then just search for "assignment result"
and only filter down those log messages.
So even though there's a lot of stuff happening here,
that filter can be really helpful to separate out
your log messages from a bunch of stuff the system is logging.
So that's it for our first few lines of Java.
In our next video we're going to write our first Android UI application.