Arrays

Related slides on offer

Figure 420. Motivating Arrays Slide presentation
final String
      karen = "Karen Smith",
      john = "John Duncan",
      paul = "Paul Jacobs",
      suzanne = "Suzanne Enders",
      peter = "Peter Phillips";  // 10 more to come ...

    System.out.println(karen);
    System.out.println(john);
...

Figure 421. Per member repeating tasks Slide presentation
  • Generate Comma separated list:

    Karen Smith, John Duncan, Paul Jacobs, Suzanne Enders, Peter Phillips
  • Generate HTML list emphasizing family names:

    <ul>
      <li>Karen <emph>Smith</emph></li>
      <li>John <emph>Duncan</emph></li>
      <li>Paul <emph>Jacobs</emph></li>
      <li>Suzanne <emph>Enders</emph></li>
      <li>Peter <emph>Phillips</emph></li>
    </ul>

Figure 422. Example: int array of primes Slide presentation
final int[] primes  = new int[5]; 

primes[0] = 2; 
primes[1] = 3;
primes[2] = 5;
primes[3] = 7;
primes[4] = 11;

int array reference variable primes.

int array allocation capable to store five values and assigning its reference to variable primes.

Assigning values referencing array positions by index values from {0,1,2,3,4}.


exercise No. 138

Assignment to final variable?

Q:

In Figure 422, “Example: int array of primes ” a final variable primes is being declared. Despite the final modifier denoting constant values we see a whole bunch of assignments i.e. primes[0] = 2. Give an explanation.

  • Explain this seeming contradiction.

  • Provide a code example demonstrating the final declaration's consequence.

A:

The variable primes carries a reference to an array. The final modifier declares this reference to become non-modifiable. On contrary changing the array's values is not being restricted. Consider:

final int[] primes  = new int[5];

primes[0] = 0;        // O.k.: Changing first array value

primes = new int[3]; // Error: Cannot assign a value to final variable 'primes'
Figure 423. Loop prime values Slide presentation
for (int i = 0; i < 5; i++) {
  System.out.println("At index " + i + ": value == " + primes[i]);
}

Result:

At index 0: value == 2
At index 1: value == 3
At index 2: value == 5
At index 3: value == 7
At index 4: value == 11

Figure 424. Mind the limit! Slide presentation
for (int i = 0; i < 6; i++) {
  System.out.println("At index " + i + ": value == " + primes[i]);
}
Result:
At index 0: value == 2
At index 1: value == 3
At index 2: value == 5
At index 3: value == 7
At index 4: value == 11
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
  at qq.arrayex.Motivate.main(Motivate.java:27)

Figure 425. Safer: Using length Slide presentation
System.out.println("primes.length == " + primes.length);
for (int i = 0; i < primes.length; i++) {
  System.out.println("At index " + i + ": value == " + primes[i]);
}
Result:
primes.length == 5
At index 0: value == 2
At index 1: value == 3
At index 2: value == 5
At index 3: value == 7
At index 4: value == 11

Figure 426. Even better: for-each style loop Slide presentation
for (final int p: primes) {
  System.out.println("value == " + p);
}
Result:
value == 2
value == 3
value == 5
value == 7
value == 11

Figure 427. Mind the limit, part two Slide presentation
final int[] primes = new int[5]; // Last index is 4 rather than 5!

primes[0] = 2;
primes[1] = 3;
primes[2] = 5;
primes[3] = 7;
primes[4] = 11;
primes[5] = 13; // Excessing array limit
Result:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
  at qq.arrayex.Motivate.main(Motivate.java:25)

Figure 428. Primitive data one step initialization Slide presentation

Combining array allocation and value assignment:

final int[]
  primes = {2, 3, 5, 7, 11};
final int[] primes = new int[5];
primes[0] = 2;
primes[1] = 3;
primes[2] = 5;
primes[3] = 7;
primes[4] = 11;

Figure 429. Reference data one step initialization Slide presentation

Combining array allocation and value assignment:

public class Rectangle {
    private int width, height;
    private boolean hasSolidBorder;
    public Rectangle(int width, int height,
                   boolean hasSolidBorder) {
        this.width = width;
        this.height = height;
        this.hasSolidBorder = hasSolidBorder;
    }
}
final Rectangle[] rectList = new Rectangle[] {
  new Rectangle(2, 5, true),
  new Rectangle(4, 1, false)
};

exercise No. 139

Converting string arrays to HTML.

Q:

Consider an array of strings. As an example we provide a list of country names:

final String[] countries = {
        "England"
        ,"France"
        ,"Germany"
};

An application is supposed to generate the following output:

<ul>
  <li>England</li>
  <li>France</li>
  <li>Germany</li>
</ul>

Implement A class method strings2html(final String [] strings) as in:

public class Stringarray2Html {

  /**
   * Create an unordered ...
   *  ...
   */
  static public String strings2html(final String [] strings) {
    ...
    return ...;
  }
}

Do not forget to provide appropriate Javadoc method and class documentation. You may want to reconsider Figure 289, “Maven javadoc:javadoc.

Generating Javadoc HTML documentation from your project should yield a result like:

Provide appropriate unit tests covering at least:

  • An empty input array.

  • An input array containing at least two strings.

A:

exercise No. 140

Route navigation

Q:

We want to estimate the amount of time being required driving a particular route. Consider the following example:

The route above may be dissected into several legs:

  1. From starting point to motorway

  2. Motorway till through road

  3. Through road till junction

  4. Junction till destination

Each leg may have a different speed limit. We thus define:

public class Segment {

   /**
    * Indication a segment does not have any speed limit.
    */
   static public final int NO_SPEED_LIMIT = 0;

   /**
    * The distance of the current leg in km.
    */
   public final double distance;

   /**
    * The current leg's speed limit in km / h.
    */
   public final int speedLimit;

   /**
    * Creating an (immutable) leg
    * @param distance {@link #distance}
    * @param speedLimit {@link #speedLimit}
    */
   public Segment(final double distance, final int speedLimit) {
      this.distance = distance;
      this.speedLimit = speedLimit;
   }
}

A given route will be defined by an array of segments:

final Segment[] route = new Segment[] {
   new Segment(2.4, 50)
  ,new Segment(5, 100)
  ,new Segment(3.1, 50)
  ,new Segment(0.8, 30)
};

Implement a method duration(...) which allows for calculation the minimum expected time required with respect to speed limits along a given route.

/**
 * Minimal time required when consequently traveling with the minimum of
 * official speed limits and the driver's personal maximum speed. If a
 * leg does not have any speed limit the value of personalSpeedLimit will
 * be used for calculation instead.
 *
 * @param route The array of segments composing a route.
 *
 * @param personalSpeedLimit The drivers personal speed limit whether or
 *        not official limits apply. Must be greater than 0.
 *
 * @return The minimal duration in (rounded) minutes with respect to all
 *         speed limits. Must be a positive (non-zero) value.
*/
static public long duration(Segment[] route, int personalSpeedLimit) {
  return 0; // TODO
}

Write Junit tests to cover different situations.

Tip

You may want to start implementing a main() method example first to gain some experience:

public class Driver {
   /**
    * @param args unused
    */
   public static void main(String[] args) {

      final Segment[] route = new Segment[] {
            new Segment(2.4, 50)
            ,new Segment(5, 100)
            ,new Segment(3.1, 50)
            ,new Segment(0.8, 30)
      };
      ...

      final long fullMinutes = ...;

      System.out.println("Minimal duration:" + fullMinutes);
}

A:

exercise No. 141

Examinations and mark frequencies

Q:

Consider an examination resulting in the following list of marks:

Participant no. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
Mark 2 1 3 3 5 4 1 2 2 4 3 2 3 3 1 5 3 4

You may represent this examination result by:

final int[] marks = {2,1,3,3,5,4,1,2,2,4,3,2,3,3,1,5,3,4};

Lecturers and participants may be interested in the distribution of marks i.e. their frequencies. Thus having marks in a range from 1 to 5 in the given example we'd like to create the following overview of marks:

Mark Frequency
1 3
2 4
3 6
4 3
5 2

Write a Java application turning an array of participants' marks into the above table of marks among with their respective frequencies. For the given example the intended terminal output reads:

Mark|frequency
----+---------
   1|3
   2|4
   3|6
   4|3
   5|2

Your application shall work for other marking schemes (i.e. marks ranging from -2 to 10) as well. Define a suitable class like:

public class MarkFrequencies {

  public final int[] frequencyByMark;
  public final int lowestMarkValue;

  public MarkFrequencies(final int[] markValues) {
    ...
  }
}

The constructor assigning values to both lowestMarkValue and frequencyByMark and is not yet implemented. Upon completion you may use class MarkFrequencies for producing the previously detailed terminal output:

final MarkFrequencies markFrequencies =
    new MarkFrequencies(new int[]{2,1,3,3,5,4,1,2,2,4,3,2,3,3,1,5,3,4});

// Create overview of marks:
//
System.out.println("Mark|frequency");
System.out.println("----+---------");

for (int i = 0; i < markFrequencies.frequencyByMark.length ; i++) {
  System.out.println("   " + (markFrequencies.lowestMark + i) + "|" +
    markFrequencies.frequencyByMark[i]);
}

Provide appropriate unit tests beforehand.

Tip

  1. Get the minimum and maximum mark of all participants beforehand.

  2. Create the int[] frequencyByMark array. Since you already know both your mark list's minimum and maximum the frequencies array's size is thus determined. Shift each mark by the mark list's minimum and regard each mark as an index value. Example:

    • The list of marks is {-2, -1, 0, 1, 2, 3}.

    • The minimum mark is -2 and the maximum equals 3.

    • The list of marks shifted by -2 will start with 0:

    • {0, 1, 2, 3, 4, 5}

    • The array of mark frequencies thus contains 6 elements.

After implementing your method extend your application to allow for being called from the command line like:

marking> mvn package
  ....
marking> java -jar target/marking-0.9.jar 2 1 3 3 5 4 1 2 2 4 3 2 3 3 1 5 3 4

Mark|frequency
----+---------
   1|3
   2|4
   3|6
   4|3
   5|2

This requires evaluating the args parameter from your main(String[] args) method.

Tip

  1. Converting a string like "5" into an int value of 5 may be achieved using:

    int value = Integer.valueOf()
  2. The maven-shade-plugin inside your project's pom.xml allows for creating executable jar archives. If your main(...) method is being defined in a class de.hdm_stuttgart.mi.marking.Marks . You may define this class to become the overall execution entry point by virtue of a corresponding pom.xml entry:

    ...
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-shade-plugin</artifactId>
      <version>3.1.0</version>
      <configuration>
        <transformers>
          <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
            <manifestEntries>
              <Main-Class>de.hdm_stuttgart.mi.marking.Marks</Main-Class>
            </manifestEntries>
          </transformer>
        </transformers>
      </configuration>
      <executions>
        <execution>
          <phase>package</phase>
          <goals>
            <goal>shade</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
    ...

    Executing mvn package will then create an executable jar archive as outlined above.

A:

The method int[] de.hdm_stuttgart.mi.marking.Marks.getFrequencies(int[] values) is being defined in a slightly more general way possibly being useful in similar situations as well. This way it becomes subject to unit testing:

public class AppTest {

  @Test
  public void testSingle() {
      Assert.assertArrayEquals(
          new int[]{1},
          Marks.getFrequencies(new int[]{-3}));
  }

  @Test
  public void testMultiple() {
      Assert.assertArrayEquals(
          new int[]{2, 1, 0, 0, 0, 2, 0, 3},
          Marks.getFrequencies(new int[]{-3, 4 , 2, -2, 4, -3, 2, 4}));
  }
}

exercise No. 142

Pangram checker

Q:

A pangram is a string containing all letters of a given alphabet at least once. As an example we consider the alphabet of ASCII letters {'a', 'b', ..., 'z'} ignoring case. Then the following string is a pangram:

The quick brown fox jumps over the lazy dog

Tip

  1. Like in Examinations and mark frequencies create an array of sufficient size regarding each character as an index value.

  2. According to the ASCII table all characters {'a', 'b', ..., 'z'} form a gapless sequence of integer values {97, 98,..., 122}.

  3. toCharArray() allows for de-composing a String into a corresponding array of char values.

  4. Normalize strings with respect to case using toLowerCase(...).

A:

In addition to the above regular solution we also provide an approach featuring Java streams with respect to the upcoming Software development 2 lecture:

static public boolean isPangram2(final String s) {
  return 26 == s.toLowerCase().chars()
    .filter(i -> i >= 'a' && i <= 'z')
    .distinct()
    .count();
}
Figure 430. Array Slide presentation
  • Series of objects having identical type.

  • Array consists of array elements.

  • Element access by index value.

  • Holding either primitive types or object references (Class instance or array).

  • Contiguous storage in memory.

  • Arbitrary array dimensions by virtue of nesting: One-dimensional, two-dimensional etc.


Figure 431. Two syntax variants Slide presentation
  1. type[] arrayName; // preferred
  2. type arrayName[];

Figure 432. Array instances are special! Slide presentation
...println("        String: " + "".getClass().getTypeName());
...println("         int[]: " + new int[]{}.getClass().getTypeName());
...println("      double[]: " + new double[]{}.getClass().getTypeName());
...println("     boolean[]: " + new boolean[]{}.getClass().getTypeName());
...println("StringBuffer[]: " + new StringBuffer[]{}.getClass().getTypeName());
        String: java.lang.String
         int[]: int[]
      double[]: double[]
     boolean[]: boolean[]
      String[]: java.lang.String[]
StringBuffer[]: java.lang.StringBuffer[]

Figure 433. Array creation details Slide presentation

Figure 434. Array parameter passing Slide presentation
public static void main(String[] args) {
  final int [] lectures = new int[3]; // Three lectures
  fill(lectures, 25); // Default lecture having 25 participants
  System.out.println("Second lecture has got " + lectures[1] +
          " participants");
}
/**
  * Initialize array with default value.
  *
  * @param values Array to be initialized.
  * @param common New value for all array elements.
  */
static void fill(final int[] values, final int common) {
  for (int i = 0; i < values.length; i++) {
    values[i] = common;
  }
}
Second lecture has got 25 participants

Figure 435. Parameter passing details Slide presentation

Figure 436. Value and reference types Slide presentation
// Value type
final boolean values[] = new boolean[]{true, true, false, true};

// Reference type
final String shapes[] = new String[]{"Triangle", "Circle"};

Same result:

final boolean values[] = {true, true, false, true};

final String shapes[] = {"Triangle", "Circle"};