tags:

views:

173

answers:

4

I've read a lot of the SCJP questions here, and all the tips and tricks from Sun and the Head First publishers, and I wonder if I am missing something.

I'm having trouble moving from knowledge about a component of Java to being able to answer a question that applies that knowledge. If you asked me a specific question about the language or API, I could answer it. However, when I am looking to apply that knowledge to answer the mock coding questions, it takes me forever to process the question, and I have trouble connecting the dots. It's like nothing clicks. Is there a process by which I can better draw conclusions about questions based upon what I know?

+4  A: 

Simple: you use it.

That may sound trite but there is no substitute for learning something new in programming than trying to do something with it. As in writing code.

If it's really new, you might start by taking an existing program and modifying it to do something you want. This will usually break it and you'll spend the next 2 hours working out why. In that 2 hours you'll have learnt more about the basics of program structure (in that language/framework), how a program is put to together and so on than 5 times that long reading it from a book.

Not that I'm suggesting books are worthless: far from it. But programming is ultimately a pragmatic discipline.

cletus
+1  A: 

When encountering a new concept, come up with a use case, and actually write some code.

For example, if we learn about Runnables and how they can be used to make new Threads, actually write some code and try it out:

Thread t = new Thread(new Runnable() {
    public void run() {
        // Do something.
    }
});
t.start();

When learning something new, there's really no substitute for actually trying things out.

Actually, I believe that going through questions on Stack Overflow and trying to answer them would be pretty good way to try to apply learned concepts. Even if one doesn't actually post an answer, going through the process of writing an answer would itself work to re-enforce the learned concept.

coobird
A: 

Really, I think this is just where experience comes in. You have to sit down and write some programs to get a feel for how things really fit together.

Eric Petroelje
+1  A: 

I'm a pretty good programmer. I have read through half of the SCJP book and when I took the test at JavaOne (for free, thankfully) I only scored a 60% on it.

What I learned from taking this exam is that they are going to try to trick you as much as possible. The only way to combat this is to start trying to code silly things and see what happens.

class Foo {
     public void doSomething() { System.out.println("Foo"); }
}
class MyFoo extends Foo {
     public void doSomething() { System.out.println("MyFoo"); }
}
public class MyClass extends MyFoo {
     Foo f;
     static {
        f = new MyFoo().doSomething();
     }
     public static void main(String args[]) {
        new MyClass();
     }
}

Create stupid examples like the one above and see what prints out. Then try playing around with Sets, TreeSets and all other kinds of Sets. Then do the same with Maps and all of the subsets of Maps. I came up with the following class that was taken from snipits from others playing with sets.

public class PlayingWithSets {
private Set<Integer> s1;
private Set<Integer> s2;

enum Test {
 A,B,C

};
/*
 * Cannot be a static block because the variable is not static. This block
 * happens before the call to super() in the constructor.
 */
{
 s1 = generateSet();
 s2 = generateSet();
}

/**
 * Helper method to set up a new HashSet
 * @return
 */
private Set<Integer> generateSet() {
 Set<Integer> s = new HashSet<Integer>();
 Random r = new Random();
 for (int i = 0; i < 20; ++i) {
  s.add(r.nextInt(30));
 }
 return s;
}

/* **********************  Merges two sets *****************************/
private void mergeSets() {
 System.out.println("Set s1 = " + s1);
 System.out.println("Set s2 = " + s2);

 /*
  * Causes an error if you use the wildcard for the generic type. I.E.
  * Set<?> s1; in the declaration.
  * 
  * The cast is needed when using wild cards for declaration. The reason
  * is that you cannot gurantee that the object is of the same type,
  * which defeats the purpose of generics and type safety.
  */
 s1.addAll(s2);
 System.out.println(s1);
}

/* ************************  Sorting on a set  ***************************/
private void sortSets() {
 /*
  * Collections.sort() is ONLY for lists.
  */
 // Collections.sort(s1);

 TreeSet<Integer> ts = new TreeSet<Integer>(s1);
 System.out.println("Sorted set s1 = " + ts);
}

/* ********************  Tests the Uniqueness of sets (i.e. no duplicates)    **************************/

static void fill(Set s) {
 s.addAll(Arrays.asList("one two three four five six seven".split(" ")));
}

public static void testSetUniqueness(Set s) {
 // Strip qualifiers from class name:
 System.out.println(s.getClass().getName().replaceAll("\\w+\\.", ""));
 fill(s);
 fill(s);
 fill(s);
 System.out.println(s); // No duplicates!
 // Add another set to this one:
 s.addAll(s);
 s.add("one");
 s.add("one");
 s.add("one");
 System.out.println(s);
 // Look something up:
 System.out.println("s.contains(\"one\"): " + s.contains("one"));
}

/* ******************  Subset / Union / Intersection **********************/

public static <T> Set<T> union(Set<T> setA, Set<T> setB) {
 Set<T> tmp = new TreeSet<T>(setA);
 tmp.addAll(setB);
 return tmp;
}

public static <T> Set<T> intersection(Set<T> setA, Set<T> setB) {
 Set<T> tmp = new TreeSet<T>();
 for (T x : setA)
  if (setB.contains(x))
   tmp.add(x);
 return tmp;
}

public static <T> Set<T> difference(Set<T> setA, Set<T> setB) {
 Set<T> tmp = new TreeSet<T>(setA);
 tmp.removeAll(setB);
 return tmp;
}

public static <T> Set<T> symDifference(Set<T> setA, Set<T> setB) {
 Set<T> tmpA;
 Set<T> tmpB;

 tmpA = union(setA, setB);
 tmpB = intersection(setA, setB);
 return difference(tmpA, tmpB);
}

public static <T> boolean isSubset(Set<T> setA, Set<T> setB) {
 return setB.containsAll(setA);
}

public static <T> boolean isSuperset(Set<T> setA, Set<T> setB) {
 return setA.containsAll(setB);
}

private void subsetUnionIntersection() {
 TreeSet<Character> set1 = new TreeSet<Character>();
 TreeSet<Character> set2 = new TreeSet<Character>();

 set1.add('A');
 set1.add('B');
 set1.add('C');
 set1.add('D');

 set2.add('C');
 set2.add('D');
 set2.add('E');
 set2.add('F');

 System.out.println("set1: " + set1);
 System.out.println("set2: " + set2);

 System.out.println("Union: " + union(set1, set2));
 System.out.println("Intersection: " + intersection(set1, set2));
 System.out.println("Difference (set1 - set2): "
   + difference(set1, set2));
 System.out
   .println("Symmetric Difference: " + symDifference(set1, set2));

 TreeSet<Character> set3 = new TreeSet<Character>(set1);

 set3.remove('D');
 System.out.println("set3: " + set3);

 System.out.println("Is set1 a subset of set2? " + isSubset(set1, set3));
 System.out.println("Is set1 a superset of set2? "
   + isSuperset(set1, set3));
 System.out.println("Is set3 a subset of set1? " + isSubset(set3, set1));
 System.out.println("Is set3 a superset of set1? "
   + isSuperset(set3, set1));

}

/* ************************         ***************************/



/**
 * @param args
 */
public static void main(String[] args) {
 /*
  * Testing different types of sets
  */
 testSetUniqueness(new HashSet());
 testSetUniqueness(new TreeSet());
 testSetUniqueness(new LinkedHashSet());

 Test test = new Test();
 Test values[] = test.values();
 System.out.println("\nValues: " + values);
 for(Test t: values) {
  System.out.println("T: " + t.toString());
 }

 PlayingWithSets p = new PlayingWithSets();
 p.mergeSets();
 p.sortSets();
 p.subsetUnionIntersection();
}
amischiefr