Working with Java Lists

As shown in the diagram below, there are three major Java class groups used for working with lists: Lists (such as List, ArrayList, LinkedList, AbstractList, Stack and Vector), Iterators (Iterator and ListIterator) and Collections. Together, these classes and their methods provide a wide spectrum options for list construction, examination and manipulation. For an example of using these classes, look here.

Common Java ArrayList Manipulation Constructs

ArrayList data structures (also called Dynamic Arrays) are a frequently used programming function. ArrayLists have an advantage over arrays - ArrayLists are not fixed in size and can be dynamically changed by adding and deleting elements. Below are some common Java array manipulation constructs. For an overview of working with Java lists, look here.

Creating a new ArrayList

Creating a new ArrayList is coded as shown below using the String type with an initial capacity of 20 entries:

ArrayList mArrayList = new ArrayList<String>(int 20);

Constructing an ArrayList from an Existing List

The example below shows how to construct an ArrayList from the individual words in a String using an intermediary List object. Notice that the sequence of objects created is: String -> String array -> List -> ArrayList

String wordString = "this is a string of words";
String[] wordsArray = wordString.split(" ");
List<String> wordsList = Arrays.asList(wordsArray);
ArrayList wordsArrayList = new ArrayList<String>(wordsList);

add( )

The example below shows how to use the ArrayList add() method to add a String to wordsArrayList::

wordsArrayList.add("Example2");

indexOf( )

The example below shows how to use the indexOf() ArrayList method find the index of an entry:

int index = wordsArrayList.indexOf("Example2");

remove( )

The example below shows how to use the ArrayList remove() method using the entry index or the entry itself:

wordsArrayList.remove(index);
wordsArrayList.remove("Example2");

sort( )

The Collections sort() methods provide a variety of options for sorting ArrayList entries. Note that the ArrayList is sorted in place without returning a new ArrayList. This can be done because the array parameter is a value pointing to the ArrayList of objects. For example, the following statement would sort the words ArrayList from the example above using a modified MergeSort algorithm in an average O(n log(n)) time performance:

Collections.sort(wordsArrayList);

binarySearch( )

The Collections binarySearch() methods provide an efficient way to find an entry in a sorted ArrayList. For example, the following statement would find the index of the wordsArrayList entry for the String Example1 in an average of O(log(n)) time performance:

int entryIndex = Collections.binarySearch(wordsArrayList, "Example1");

iterator( )

The Iterator Class and ArrayList interator() method can be used to iterate over the entries of an ArrayList as shown in the example below :

Iterator mIterator = wordsArrayList.iterator();
while(mIterator.hasNext()){
System.out.println(mIterator.next());
};

Common Java Array Manipulation Constructs

Working with array data structures is one of the most frequently used programming functions. Arrays are implemented in a number of Java classes, such as String, Integer, and Boolean. Those arrays can be manipulated using the Java Arrays class (note that the Arrays class name is a plural). Below are some common Java array manipulation constructs.

split( )

The String split() method separates string characters into array entries using a supplied regular expression. For example, the following statement would create entries in the String array wordsArray using a blank character as a regular expression separator for processing the String wordString:

String wordString = "this is a string of words";
String[] wordsArray = wordString.split(" ");

sort( )

The Arrays sort() methods provide a variety of options for sorting array entries. Note that the array is sorted in place without returning a new array. This can be done because the array parameter is a value pointing to the array of objects. For example, the following statement would sort the words array from the split() example above using a Quicksort process in an average O(n log(n)) time performance:

Arrays.sort(wordsArray);

binarySearch( )

The Arrays binarySearch() methods provide an efficient way to find an entry in a sorted array. For example, the following statement would find the index of the array wordsArray entry for the String entryValue in an average of O(log(n)) time performance:

int entryIndex = Arrays.binarySearch(wordsArray, entryValue);

for( )

The for() construct can be used to iterate over the entries in an array. For example, the following statement would iterate over and print every entry in wordsArray:

for (String word : wordsArray) {System.out.print(word);}

If you want to know and use the index of each entry, then this construct can be used:

for (int i=0; i<wordsArray.length; i++) {System.out.print(wordsArray(i);}

Android Data View Adapters Overview

Android APIs provide classes and methods to facilitate displaying data in various forms, such as lists, arrays and custom layouts. The graphic below shows how the various classes and methods interact to produce the desired result.

Some examples of coding and use are:

Data

The data to be displayed can be in such forms as an Array, List, File or SQLite database. If a database is used, a Cursor object is also employed. A simple array of String values might be created and converted to an ArrayList like this:

String[] mStringArray = new String[] { "blue", "green", "yellow",
        "red", "orange", "black", "white", "purple"};
List<String> mList = Arrays.asList(mStringArray);
ArrayList<String> mArrayList = new ArrayList<String>(mList);

Cursor

Cursor is an interface that provides random read-write access to the result set returned by a database query. Setting up a Cursor for an SQLite database might look like this:

MySQLiteOpenHelper mDatabaseHelper = new MySQLiteOpenHelper(this);
Cursor mCursor = mDatabaseHelper.getDataIntoCursor();
ListView mListView = (ListView) findViewById(R.id.mListView);
MyCursorAdapter mCursorAdapter = new MyCursorAdapter(this, mCursor);
mListView.setAdapter(mCursorAdapter);

class MyCursorAdapter extends CursorAdapter {

    public MyCursorAdapter(Context context, Cursor c) {
        super(context, c);
    }
    // Implement CursorAdapter bindView method.
    public void bindView(View view, Context context, Cursor cursor) {
        String name = cursor.getString(1);
        TextView textView = (TextView) view;
        textView.setText(name);
    }
    // Implement CursorAdapter newView method.
    public View newView(Context context, 
                         Cursor cursor, ViewGroup parent) {
        TextView view = new TextView(context);
        return view;
    }
}
private final class MySQLiteOpenHelper extends SQLiteOpenHelper {

    private static final String DATABASE_NAME = "myDatabase";
    private static final int DATABASE_VERSION = 1;
    private static final String CREATE_TABLE_TIMELINE = 
        "CREATE TABLE IF NOT EXISTS table_name 
        (_id INTEGER PRIMARY KEY AUTOINCREMENT, name varchar);";

    public DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_TABLE_TIMELINE);
        db.execSQL("INSERT INTO ddd (name) VALUES ('Name1')");
        db.execSQL("INSERT INTO ddd (name) VALUES ('Name2')");
        db.execSQL("INSERT INTO ddd (name) VALUES ('Name3')");
    }
    @Override
    public void onUpgrade(SQLiteDatabase db, 
                          int oldVersion, int newVersion) {
    }
    public Cursor getDataIntoCursor() {
        String selectQuery = "SELECT  * FROM table_name;
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);
        return cursor;
    }
}

Adapters

An Adapter acts as a bridge between an AdapterView and the underlying data for that view. A custom array adapter defined in Java might look like this:

class MyArrayAdapter extends ArrayAdapter<String> {
    HashMap<String, Integer> mHashMap = new HashMap<String, Integer>();
    public MyArrayAdapter(Context context, int textViewResourceId,
        List<String> objects) {
      super(context, textViewResourceId, objects);
      for (int i = 0; i < objects.size(); ++i) {
        mHashMap.put(objects.get(i), i);
      }
    }
    @Override
    public long getItemId(int position) {
      String item = getItem(position);
      return mHashMap.get(item);
    }
    @Override
    public boolean hasStableIds() {
      return true;
    }
 }

The custom array adapter mArrayAdapter would be instantiated and linked to a ListView mListView with Java code like this:

setContentView(R.layout.mLayout);
final ListView mListView = (ListView) findViewById(R.id.listview);
final MyArrayAdapter mArrayAdapter = new MyArrayAdapter(this,
        android.R.layout.simple_list_item_1, mArrayList);
    mListView.setAdapter(mArrayAdapter);

AdapterView

An AdapterView is a view whose children are determined by an Adapter. You might use an AdapterView like this:

private OnItemClickListener mMessageClickedHandler = 
  new OnItemClickListener() {
    public void onItemClick(AdapterView parent, 
                            View v, int position, long id) {
        // Do something in response to the click
    }
};
listView.setOnItemClickListener(mMessageClickedHandler);

View

View is the basic building block for user interface components. A view occupies a rectangular area on the screen and is responsible for drawing and event handling. A ListView contained in a layout might look like this:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/mLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <ListView
        android:id="@+id/mListView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>
</LinearLayout>

ViewGroup

ViewGroup is a special view that can contain other views called children. A ViewGroup defined in XML might look like this:

<ViewGroup xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@id/mViewGroup"
    android:layout_height="wrap_content"
    android:layout_width="fill_parent" >
    <TextView
        android:id="@id/mTextView"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent"
    </TextView>
</ViewGroup>

Layout

A layout defines the visual structure for a user interface. A layout might look like this:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/mLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <ListView
        android:id="@+id/mListView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>
</LinearLayout>

Activity

An Activity provides a screen with which users can interact.

public class MyActivity extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    . . .
  }
}

Fragment

A Fragment represents a behavior or a portion of user interface an an Activity. Fragment code might look like this:

public class ArticleFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, 
                             ViewGroup container,
        Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.article_view, 
                                container, false);
    }
}

Android Job Interview Topics

Because Android contains an extremely large number of Classes and Methods, it's impossible to hold all of the syntax and details in your head. For this reason, I've found that Android interview questions tend to be more conceptual in nature. For example, you might be asked how you'd approach a given problem using Android and Java constructs.

As you study the commonly used interview topics below, try to retain the main ideas and some relevant details. 

Android Listeners and Toasts

This video, part of my Android Quick Code Access series of posts, explains Android Listeners and Toasts. It's from my course Learning Android App Programming published by InfiniteSkills.

The Java code for the example is below...

import java.util.Random;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class ListenerToastMain extends Activity {
	
    // onCreate method.
	@Override
	protected void onCreate(Bundle savedInstanceState) {
	    super.onCreate(savedInstanceState);
	    
	    // Initialize display.
	    setContentView(R.layout.main);
	        
           // Declare button variable for Get Answer.
	    Button getAnswer =
               (Button)findViewById(R.id.getAnswerButton);
	        
	    // Set listener for button.
	    getAnswer.setOnClickListener(getAnswerListener);    
	}   
    // Define OnClickListener for getAnswer button.
    private OnClickListener getAnswerListener = new OnClickListener() {
        public void onClick(View v){
       		
            // Generate answer number.
            Random toastGen = new Random();
            int toastNum = toastGen.nextInt(19);
            toastNum++;
       		
            // Get answer text.
            CharSequence text = "";
            switch (toastNum) {
                case 1:  text = getString(R.string.answer1);  break;
                case 2:  text = getString(R.string.answer2);  break;
                case 3:  text = getString(R.string.answer3);  break;
                case 4:  text = getString(R.string.answer4);  break;
                case 5:  text = getString(R.string.answer5);  break;
                case 6:  text = getString(R.string.answer6);  break;
                case 7:  text = getString(R.string.answer7);  break;
                case 8:  text = getString(R.string.answer8);  break; 
                case 9:  text = getString(R.string.answer9);  break;
                case 10: text = getString(R.string.answer10); break;
                case 11: text = getString(R.string.answer11); break;
                case 12: text = getString(R.string.answer12); break;
                case 13: text = getString(R.string.answer13); break;
                case 14: text = getString(R.string.answer14); break;
                case 15: text = getString(R.string.answer15); break;
                case 16: text = getString(R.string.answer16); break;
                case 17: text = getString(R.string.answer17); break;
                case 18: text = getString(R.string.answer18); break;
                case 19: text = getString(R.string.answer19); break;
                case 20: text = getString(R.string.answer20); break;       		    
            }
            // Toast answer.
            Context context = getApplicationContext();
            int duration = Toast.LENGTH_LONG;
            Toast toast = Toast.makeText(context, text, duration);
            toast.show();
        }	        	
    };
}

Android Database Query Display

This is part of the Android Quick Code Access series of posts. The code below displays the results of a Database Query. You'll need to run the Query code in a background thread in your production version.

// Database Display Activity.
public class DatabaseDisplayActivity extends ListActivity {

   // Database display columns.
   private static final String[] PROJECTION = new String[] {
    	COLUMN_NAME_1,   // 0 Position
    	...
   }
   @Override
   // Activity onCreate method.
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
		
       // Database Query. 
       Cursor cursor = managedQuery(
            MyContent.CONTENT_URI,
            PROJECTION,
            null,
            null,
            MyContent.DEFAULT_SORT_ORDER  
       );		
       // Cursor columns to display.
       String[] dataColumns = {     		
            COLUMN_NAME_1,
            ...
       } ;
       // View IDs for formatting.
       int[] viewIDs = { 	
            android.R.id.text1,   
            ...		
       };
       // Adapter for the ListView.
       SimpleCursorAdapter adapter = new SimpleCursorAdapter(       		
            this,                                 
            android.R.layout.simple_list_item_1, 
            cursor,  
            dataColumns,
            viewIDs   
            );
       // Binder to display row results.
       adapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
           public boolean setViewValue(
                View view, Cursor cursor, int columnIndex) {
        		
                // Get row of cursor.
                String displayText = 
                    DatabaseUtils.dumpCurrentRowToString(cursor);

                // Set text in display.
                ((TextView) view).setText(displayText);
                return true;
            }
       });        
       // List Adapter.
       setListAdapter(adapter);	
   }
}

Android Eclipse Waiting for Debugger

This is part of the Android Quick Code Access series of posts. Depending on the specifics of your Android code, you may need to add code to force a wait for the Eclipse debugger. This is especially true for asynchronous code functions like background threads. Without the code below, you may see Eclipse break points not being triggered. You might think that your code is broken, when in fact you just need to add a code line to force it to wait for the debugger to catch up.

android.os.Debug.waitForDebugger()

Android Allowing Main Thread I/O

An important aspect of Android App design is to never block the main UI thread with long running tasks. Doing so can result in an Application Not Responding (ANR) condition that can cause your App to be stopped. To prevent ANR conditions, always perform long running tasks such as I/O in background threads.

If you need to test I/O access from the main UI thread, you'll need to change the Thread Policy as shown below. Only do this for testing. In your production App, make sure you perform I/O operation in a background thread.

StrictMode.ThreadPolicy policy = 
    new  StrictMode.ThreadPolicy.Builder().permitAll().build(); 
StrictMode.setThreadPolicy(policy);

Android Image Button Listener

This is part of the Android Quick Code Access series of posts. For more information on handling Buttons, see the Android Button class.

// Listener for Button.
ImageButton imageButton = (ImageButton) findViewById(R.id.myButton);
imageButton.setOnClickListener(new OnClickListener() {
			
    // Button onClick method.
    @Override
    public void onClick(View v) {
				
        // Take action here.
         . . .

    } 
});