Java 學習記錄 41 — List and ArrayList

張小雄
11 min readFeb 19, 2021

今天學習 ArrayList

import java.util.Scanner;public class ListAndArrayList {    private static Scanner scan = new Scanner(System.in);
private static int[] baseData = new int[3];
public static void main(String[] args) {
System.out.println("Enter 3 integers: ");
getInput();
printArray(baseData);
resizeArray();
// System.out.println("Enter 5 integers: ");
// getInput();
baseData[3] = 77;
baseData[4] = 78;
printArray(baseData);
}
private static void getInput() {
for (int i = 0; i < baseData.length; i++) {
baseData[i] = scan.nextInt();
}
}
private static void printArray(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
private static void resizeArray() {
int[] original = baseData;
baseData = new int[5];
for (int i = 0; i < original.length; i++) {
baseData[i] = original[i];
}
}
}

之前剛學過的 Array 如果要改裡面的數量時

就會像上面代碼一樣 弄得很麻煩

main.java

import java.util.ArrayList;
import java.util.Scanner;
public class Main {
private static Scanner scanner = new Scanner(System.in);
private static GroceryList groceryList = new GroceryList();
public static void main(String[] args) {
boolean quit = false;
printInstructions();
while (!quit) {
System.out.println("Enter your choice: ");
int choice = scanner.nextInt();
scanner.nextLine();
switch (choice) {
case 0:
printInstructions();
break;
case 1:
groceryList.printGroceryList();
break;
case 2:
addItem();
break;
case 3:
modifyItem();
break;
case 4:
removeItem();
break;
case 5:
searchItem();
break;
case 6:
processArrayList();
case 7:
quit = true;
System.out.println("Good bye!");
break;
}
}
} public static void printInstructions() {
System.out.println("\nPress ");
System.out.println("\t 0 - To print choice options.");
System.out.println("\t 1 - To print the list of grocery items.");
System.out.println("\t 2 - To add an item to the list.");
System.out.println("\t 3 - To modify an item in the list.");
System.out.println("\t 4 - To remove an item from the list.");
System.out.println("\t 5 - To search for an item in the list.");
System.out.println("\t 6 - To quit the application.");
}
private static void addItem() {
System.out.println("This is add item function.");
System.out.println("Please enter item name to add: ");
String item = scanner.nextLine();
groceryList.addGroceryItem(item);
} private static void modifyItem() {
System.out.println("This is modify item function.");
System.out.println("Enter current item name: ");
String item = scanner.nextLine();
if (groceryList.onFile(item)) {
System.out.println("Enter replacement item to modify: ");
String newItem = scanner.nextLine();
groceryList.modifyGroceryItem(item, newItem);
} else {
System.out.println(item + " is not in grocery list");
}
} private static void removeItem() {
System.out.println("This is remove item function.");
groceryList.printGroceryList();
System.out.println("Enter item name to remove: ");
String item = scanner.nextLine();
groceryList.removeGroceryItem(item);
}
private static void searchItem() {
System.out.println("This is search item function.");
System.out.println("Enter Item to search: ");
String searchItem = scanner.nextLine();
if (groceryList.onFile(searchItem)) {
System.out.println("found item: " + searchItem);
} else {
System.out.println("Not found: " + searchItem);
}
} public static void processArrayList() {
ArrayList<String> newArray = new ArrayList<String>();
newArray.addAll(groceryList.getGroceryList());
// same as line 101~102
ArrayList<String> newArray2 = new ArrayList<String>(groceryList.getGroceryList());
// ArrayList convert to normal array
String[] myArray = new String[groceryList.getGroceryList().size()];
myArray = groceryList.getGroceryList().toArray(myArray);
}
}

GroceryList.java

import java.util.ArrayList;public class GroceryList {
private ArrayList<String> groceryList = new ArrayList();
public ArrayList<String> getGroceryList() {
return groceryList;
}
public void addGroceryItem(String item) {
groceryList.add(item);
System.out.println("You had add - " + item + " - to grocery list");
}
public void printGroceryList() {
System.out.println("You have " + groceryList.size() + " items in your grocery list.");
for (int i = 0; i < groceryList.size(); i++) {
System.out.println((i + 1) + ". " + groceryList.get(i));
}
}
public void modifyGroceryItem(String currentItem, String newItem) {
int position = findItem(currentItem);
if (position >= 0) {
modifyGroceryItem(position, newItem);
}
} private void modifyGroceryItem(int position, String item) {
groceryList.set(position, item);
System.out.println("Grocery Item " + (position + 1) + " has been modified.");
}
public void removeGroceryItem(String item) {
int position = findItem(item);
if (position >= 0) {
removeGroceryItem(position);
} else {
System.out.println("This item is not in grocery list.");
}
}
private void removeGroceryItem(int position) {
String theItem = groceryList.get(position);
groceryList.remove(position);
System.out.println("item: " + theItem + " had been removed.");
}
private int findItem(String searchItem) {
return groceryList.indexOf(searchItem);
}
public boolean onFile(String searchItem) {
int position = findItem(searchItem);
return position >= 0;
}
}

創了一個購物清單的功能

使用這種 ArrayList 就不用像使用 Array 添加跟刪除元素時都要重新創立一次

內部自動幫你完成操作

在 GroceryList.java 中

有些方法有重寫是因為 (例如:modifyGroceryItem)

要讓調用者 可用最直覺的方式去使用

一開始寫的是兩個參數

調用者還要知道位置參數是多少才能調用

顯然是非常不方便

所以重寫一個 只需輸入一個參數的 method

那就大大增加方便性啦

甚至還把重寫的 method 改成 private

這樣就只提供我們允許的 method 給調用者做使用

也實現了 Encapsulation 若以後要修改裡面的功能

不用回到調用的地方全部一起修改

Vimal 同學問:

Why are we making duplicate functions?

Goran 助教回答:

what you are suggesting is not good design. There is well known principle called single responsibility. In short it means 1 class is responsible for 1 problem. In this case GroceryList class is responsible for managing list of groceries it does not need to know how the items will be added to list. Items could be added with scanner (via console), another way would be with some user interface, another way could be from database, another way could be from web service and so on.

The idea is that GroceryList does not need to know how you will add item, it just needs to have functionality add/remove items etc, nothing else. That way your GroceryList can be used with some other application. I had a case where there was item list holding products but it was used on server with web app and on desktop with user interface, so instead of writing 2 classes that represent product list it was easier to use the same class.

Hope that helps.

我簡單總結:

Mingyu 同學問:

Hi, Tim. In Lecture 57, I did not see any changes after I removed all the scanner.nextLine() methods, is it just a safe way to make sure that the scanner read the upcoming input correctly by cleaning its buffer but what does that mean exactly?

Tim 老師回答:

If you do a scanner.nextInt(), then you must do a scanner.nextLine() to clear out the buffer.

That’s because a nextInt() reads only the numbers, and not the end of line characters.

If you are reading a string, then you do not need to do an extra .nextLine() call, since the original .nextLine() called read the entire string and the end of line characters.

The bottom line is, if you use .nextInt() it needs a .nextLine() before you can do another .nextInt() or .nextLine()

Kalyan 同學問:

1.Why don’t we use static keyword for Array List?

2.Since we are not using static keyword it should not be accessed by other methods? But it is accessible?Scanner is also a class but it is accessible with only static keyword?

J 同學回答:

Static means that there is only one version of whatever comes with it, even if you have a million different objects, they all share the same base. You could make a list static. But it would impractical. Imagine you write a shopping list program. It allows users to make a shopping list and achieves this by saving each item as a value into an ArrayList.

Now, if you made this ArrayList static and it had only 1 user then there would be no problem.

But what if there are 2 users who both need to do their shopping and have different lists?

How would you distinct the lists from another? You wouldnt.

So you need to instantiate the arraylist. The only way to do this by making the list not static (and not final).

小挑戰:

Create a program that implements a simple mobile phone with the following capabilities.

Able to store, modify, remove and query contact names.

You will want to create a separate class for Contacts (name and phone number).

Create a master class (MobilePhone) that holds the ArrayList of Contacts

The MobilePhone class has the functionality listed above.

Add a menu of options that are available.

Options: Quit, print list of contacts, add new contact, update existing contact, remove contact

and search/find contact.

When adding or updating be sure to check if the contact already exists (use name)

Be sure not to expose the inner workings of the Arraylist to MobilePhone

e.g. no ints, no .get(i) etc

MobilePhone should do everything with Contact objects only.

解答:

Contact.java

public class Contact {
private String name;
private String phoneNumber;
public Contact(String name, String phoneNumber) {
this.name = name;
this.phoneNumber = phoneNumber;
}
public static Contact createContacts(String name, String phoneNumber) {
return new Contact(name, phoneNumber);
}
public String getName() {
return name;
}
public String getPhoneNumber() {
return phoneNumber;
}
}

MobilePhone.java

import java.util.ArrayList;public class MobilePhone {
private String myNumber;
private ArrayList<Contact> myContacts;
public MobilePhone(String myNumber) {
this.myNumber = myNumber;
this.myContacts = new ArrayList<Contact>();
}
public boolean addNewContact(Contact contact) {
if (findContact(contact.getName()) >= 0) {
System.out.println("Contact is already on file.");
return false;
}
myContacts.add(contact);
return true;
}
private int findContact(Contact contact) {
return this.myContacts.indexOf(contact);
}
private int findContact(String contactName) {
for (int i = 0; i < this.myContacts.size(); i++) {
Contact contact = this.myContacts.get(i);
if (contact.getName().equals(contactName)) {
return i;
}
}
return -1;
}
public String queryContact(Contact contact) {
if (findContact(contact) >= 0) {
return contact.getName();
}
return null;
}
public Contact queryContact(String name) {
int position = findContact(name);
if (position >= 0) {
return this.myContacts.get(position);
}
return null;
}
public boolean updateContact(Contact oldContact, Contact newContact) {
int foundPosition = findContact(oldContact);
if (foundPosition < 0) {
System.out.println(oldContact.getName());
return false;
} else if (findContact(newContact.getName()) != -1) {
System.out.println("Contact with name " + newContact.getName() +
" already exists.");
return false;
}
this.myContacts.set(foundPosition, newContact);
System.out.println(oldContact.getName() + " was not found.");
return true;
} public boolean removeContact(Contact contact) {
int foundPosition = findContact(contact);
if (foundPosition < 0) {
System.out.println(contact.getName());
return false;
}
this.myContacts.remove(foundPosition);
System.out.println(contact.getName() + " was deleted.");
return true;
}
public void printContacts() {
System.out.println("Contact List");
if (this.myContacts.size() == 0) {
System.out.println("You don't have any contact now.");
return;
}
for (int i = 0; i < this.myContacts.size(); i++) {
System.out.println((i + 1) + ". " +
"Name: " + this.myContacts.get(i).getName() +
" ---> " +
"Number: " + this.myContacts.get(i).getPhoneNumber());
}
}
}

main.java

import java.util.Scanner;public class Main {
private static Scanner scanner = new Scanner(System.in);
private static MobilePhone mobilePhone = new MobilePhone("0988-321-123");
public static void main(String[] args) {
boolean quit = false;
startPhone();
printActions();
while (!quit) {
System.out.println("Enter number to action: ");
int choice = scanner.nextInt();
scanner.nextLine();
switch (choice) {
case 0:
quit = true;
System.out.println("Good bye!");
break;
case 1:
mobilePhone.printContacts();
break;
case 2:
addNewContact();
break;
case 3:
updateContact();
break;
case 4:
removeContact();
break;
case 5:
queryContact();
break;
case 6:
printActions();
break;
}
}
} public static void addNewContact() {
System.out.println("This is addNewContact function.");
System.out.println("Enter new contact name: ");
String name = scanner.nextLine();
System.out.println("Enter phone number: ");
String phone = scanner.nextLine();
Contact newContact = Contact.createContacts(name, phone);
if (mobilePhone.addNewContact(newContact)) {
System.out.println("New contact added: " + name + ", phone = " + phone);
} else {
System.out.println("Cannot add, " + name + " already phone...");
}
} private static void updateContact() {
System.out.println("This is updateContact function.");
System.out.println("Enter existing name to update: ");
String name = scanner.nextLine();
Contact existingContactRecord = mobilePhone.queryContact(name);
if (existingContactRecord == null) {
System.out.println("Contact not found.");
return;
}
System.out.println("Enter new contact name");
String newName = scanner.nextLine();
System.out.println("Enter new contact phone number");
String newNumber = scanner.nextLine();
Contact newContact = Contact.createContacts(newName, newNumber);
if (mobilePhone.updateContact(existingContactRecord, newContact)) {
System.out.println("Successfully updated record.");
} else {
System.out.println("Error updated.");
}
}
private static void removeContact() {
System.out.println("This is removeContact function.");
System.out.println("Enter existing name to remove: ");
String name = scanner.nextLine();
Contact existingContactRecord = mobilePhone.queryContact(name);
if (existingContactRecord == null) {
System.out.println("Contact not found.");
return;
}
if (mobilePhone.removeContact(existingContactRecord)) {
System.out.println("Successfully deleted");
} else {
System.out.println("Error deleting contact");
}
}
private static void queryContact() {
System.out.println("This is queryContact function.");
System.out.println("Enter existing name to query: ");
String name = scanner.nextLine();
Contact existingContactRecord = mobilePhone.queryContact(name);
if (existingContactRecord == null) {
System.out.println("Contact not found.");
return;
}
System.out.println("Name: " + existingContactRecord.getName() + " phone number is " + existingContactRecord.getPhoneNumber());
}
private static void startPhone() {
System.out.println("Start phone ------");
}
private static void printActions() {
System.out.println("\nAvailable actions:\nPress number of list.");
System.out.println("0 - to shutdown\n" +
"1 - to print contacts\n" +
"2 - to add a new contact\n" +
"3 - to update an existing contact\n" +
"4 - to remove an existing contact\n" +
"5 - query if an existing contact exists\n" +
"6 - to print a list of available actions.");
}
}

我的領悟:

原本 method 的參數都是用 String name、int number 等

這次突然放了一個自己創的 class,剛開始搞不懂看了半天

去翻QA助教回答才理解

medthod(String name) 就只是用原本定義好的 class String

而我們這次用的就是自創的 class

method(自創class name)

這都是屬於 OOP 的範疇

突然有一種茅塞頓開的感覺

但這次的內容還是很難

為了搞懂前後看了3次

也只是看懂能修改

要我完全自己寫就無法

同學問:

Hi,

i was experimenting on the find feature to look for a contact base on their name,

First, i tried to use this:

if(mobile.getName() == name) {
return i;
}

In which it gives me false even if i key in correctly (case sensitive considered)

So now, i tried this:

if(mobile.getName().equals(name)) {
return i;
}

and it works..

Can you please explain the rough idea, why the bottom one works, and the top one doesn’t? does it only affects on objects?

老師答:

== only returns true if the same object in memory is compared.

.equals() on the other hand correctly tests if the name is the same.

If you want to check object equality, use .equals(), for primitive types

or if you want to check if the same object instance is identical use ==.

我簡單總結:

== 為同個物件的比較

.equals() 名稱的比較

同學問:

Hi Tim.

you mentioned in the begining of the money while writing this code:
that its important for it to be static.
could you please explain this more in depth? im still trying to grasp completely the concepts of STATIC and RETURN. i feel its at the tip of my fingers but i still dont get it fully.maybe you could explain it to me better.
thankyou!

public static Contact createContact(String name, String phoneNumber) {
return new Contact(name, phoneNumber);
}

同學答:

These two topics can be difficult to grasp but let’s step away from those terms for a couple moments and try to think of a real world analog for these. Let’s say you’re at a bank, you the customer stand on one side of the counter while the employees are behind the counter. You want to make a deposit so you have filled out a deposit slip and have the money in hand. You pass the employee your deposit slip and the money. They work for a few moments then print out a receipt and hand it to you. You have just completed a real life equivalent of calling a method. The deposit slip and money that you’re holding are your arguments that you pass to the method, they are also the parameters that you are meeting in order to perform a transaction (run the method). The receipt that is printed and handed back to you is the same as a method RETURNing something back to the code that called it.

Static is a bit more complicated to explain because it behaves differently if it is applied to a method or a variable(field). A static variable is a variable that remembers its value in between uses. It’s created outside of a method and methods can interact with it and change the value at will but instead of being destroyed after the method is done the variable remains unchanged until the next method comes along to modify it.

A static method on the other hand is a method that is a member of a class but is capable of standing alone. Normally when working with objects you have to create an instance of an object in order to call the methods that it contains. An example of this is Car car = new Car(); This creates a new instance of the Car class type and stores it in a variable called car. Then you call methods belonging to that class by running car.methodName() Because static methods are standalone that means you can call them without creating a new instance of the class type. You do this by specifying the class then method name. Car.methodName() This runs the method methodName inside the Car class, but doesn't need to create a new Car in order to do it.

The code that you pasted up above is a “stand alone” method that creates a new instance of a Contact object and passes it back to the code that called it. This allows you to create a new Contact without needing to make a temporary instance of the class that createContact() belongs to before calling the method.

我簡單總結:

用 static 就不需另外創 object 來調用 method

--

--