If we assume the input list is sorted, we should be able to do this in O(N), with no additional space necessary.
public static Integer maxUnduplicatedVal(ArrayList<Integer> lst){
    if(lst == null || lst.isEmpty()) 
        return null;
    if(lst.size() == 1) return lst.get(0);
    if(! lst.get(lst.size() - 1).equals(lst.get(lst.size() - 2))) 
        return lst.get(lst.size() - 1);
    for(int i = lst.size() - 2; i > 0; i--){
        Integer next = lst.get(i + 1);
        Integer here = lst.get(i);
        Integer prev = lst.get(i - 1);
        if(! next.equals(here) && ! prev.equals(here)) return here;
    }
    if(! lst.get(0).equals(lst.get(1))) return lst.get(0);
    return null; //All duplicates
}
If it is not always sorted, the fastest way is to create a copy of the list then remove duplicates and just call the max function in Collections. Making the copy is a really good idea - getters really shouldn't alter the collection they receive. (This includes sorting the given set).
private static List<Integer> getUniques(List<Integer> list) {
    HashMap<Integer, Boolean> flagMap = new HashMap<>();
    //Total Loop: O(N)
    for(Integer i : list){
        if(flagMap.containsKey(i)) flagMap.put(i, false); //O(1)
        else flagMap.put(i, true); //O(1)
    }
    ArrayList<Integer> result = new ArrayList<Integer>();
    //Total Loop: O(N)
    for(Integer i : list){
        if(flagMap.get(i)) result.add(i); //O(1)
    }
    return result;
}
public static Integer maxUnduplicatedVal(ArrayList<Integer> lst){
    List<Integer> lstCopy = getUniques(lst);
    return Collections.max(lstCopy);
}
This is still O(N), albiet with some extra space requirements.