CSIT115 Class 19 ArrayList<String>

ArrayList<String> is in competition with String arrays for holding Strings numbered 0, 1, 2, 3, …

The biggest difference is that ArrayList<String> is stretchy compared to an array of Strings.  When we create an array of Strings, we must decide on its size:

String[] names = new String[10];

This array can hold exactly 10 Strings, number 0, 1, 2, …, 9.  If we later want to hold 12 Strings, we would have to set up a new bigger array and copy the String references into it. 

With ArrayList<String>, we create an empty list and then add to it, with no limit other than the actual size of computer memory.

ArrayList<String> names = new ArrayList<String>();  // create an  empty ArrayList of String

names.add(“Bob”);  // add a String, which becomes #0

String n = names.get(0);  // access the one string in names.

Last time we took advantage of this stretchiness to put all the words of hamlet.txt into an ArrayList<String> words, so that we can output them in reverse order. 

We can do other things with this ArrayList<String> called words.  

Example: find the longest word in Hamlet (i.e., in hamlet.txt). Recall that all the words have been read into ArrayList<String> words, using code like that on pg. 380 to parse the words.

int maxLength = 0;

for (int i=0; i < words.size(); i++) {

  if (words.get(i).length() > maxLength) {

      maxLength = words.get(i).length();

  }

}

 

If we had the words in a String array called words, this code would be similar:

int maxLength = 0;

for (int i=0; i < words.length; i++) {   // .length vs. .size()

  if (words[i].length() > maxLength) {   // [i] vs. .get(i)

      maxLength = words.get(i).length();

  }

}

 

We noted that there are three common length forms:

·         Array named a has length a.length

·         String named s has length s.length()

·         ArrayList named al has length al.size()

A Powerful Search capability of ArrayList<String>: contains

The contains method of ArrayList searches through the ArrayList looking for a matching element to one given in its argument. For ArrayList<String>, contains(matchString) looks for a String in the ArrayList that is equals (using String .equals) to matchString.

Example: Does the word “apple” appear anywhere in hamlet.txt?

We can answer this by using words.contains, knowing that all the words of hamlet.txt are in the ArrayList<String> words:

if (words.contains(“apple”))

   System.out.println(“ Hamlet has the word apple”);

 

Of course this isn’t magic. To implement contains, the ArrayList code must scan the ArrayList until it finds a match, possibly reading the whole list.  That can take a little time.  But we don’t have to code this loop, it’s all happening inside contains.  This makes our lives as programmers a little easier.

 

An IT example.

Suppose we have assembled two files of usernames as follows:

Users_weak_pws.dat: usernames of users with weak passwords, obtained by trying all “easy” passwords to login, a standard test.  We are given this file, the result of such testing.

Users_priv.dat: usernames of users with system privileges, obtained from system information.

 

We want to make a list of privileged users with weak passwords, these being the most dangerous to the health of the system.  In other words, we want a list of users who show up on both given lists.

 

How can we do this?

We can use Linux commands “sort” and “join”, as follows:

sort users_weak_pws.dat > users_weak_sorted.dat

sort users_priv.dat > users_priv_sorted.dat

join users_weak_sorted.dat users_priv_sorted.dat

<outputs usernames showing up on both lists>

 

Now of course this is not part of this course, but eventually you will learn such tricks in Linux Systems Admin courses. More to the point, we can do this using Java, ArrayLists, and contains, as follows:

 

Read users_weak_pws.dat into ArrayList<String> weakOnes, following the code we used for words.

Read users_priv.dat into ArrayList<String> privOnes, following the code we used for words.

 

For a username found in privOnes, see if it occurs also in weakOnes by weakOnes.contains(username), and if so print it out.

Do this for each username in privOnes.  Here is the code:

 

for (int i=0; i< privOnes.size(); i++) {

   String user = privOnes.get(i);

   if (weakOnes.contains(user)) {

     System.out.println(“User “ + user + “ is privileged and has a weak password”);

   }

}

 

Final topic today: for-each loops.  We have been using the traditional for loop that loops through index values for arrays and ArrayLists. There is another for loop syntax that never mentions the index values but instead loops through the values themselves, i.e., the Strings in the case of ArrayList<String>. This is discussed on pg. 642.  As an example, take our earlier for loop:

 

int maxLength = 0;

for (int i=0; i < words.size(); i++) {

  if (words.get(i).length() > maxLength) {

      maxLength = words.get(i).length();

  }

}

 

Using a for-each loop, this can be written:

 

int maxLength = 0;

for (s in words) {

  if (s.length() > maxLength) {

      maxLength = s.length();

  }

}

 

This does look simpler, but it does exactly the same work. I don’t care which form you use—it’s your choice as a programmer.