Given the following context:
public interface IAdditive<T> {
/** True if still capable to crunch. */
boolean canCrunch();
/** True if capable to crunch with B. */
boolean canCrunch(T other);
/** Returns a new T which is the sum of this and other */
T crunch(T other);
}
class A implements IAdditive<A> {
..
A crunch(A other) {...}
}
class B extends A {
...
B crunch(B other) {...}
}
class C implements IAdditive<C> {
...
C crunch(C other) {...}
}
Now I want to "crunch" a Stream of Implementations
/** Chrunches the streams where possible */
public Stream<A> crunchStream(Stream s) {
return s.map(...);
}
I am stuck with my rather naive approach:
public Set<A> collect(Stream<A> stream) {
Set<I> res = new HashSet<>();
Set<I> set = stream
.filter(IAdditive::canCrunch)
.collect(Collectors.toSet());
set.forEach(setItem -> set.stream()
.filter(concurrentItem -> concurrentItem.canCrunch(setItem))
.map(setItem::crunch)
.forEach(res::add));
return res;
}
That should be flawed. I am unfolding the stream, add mandatory complexity, and If I want the interface to offer that in a default method I would have to use rawtypes.
I believe I could use some help :-)
Based on your comments, I think this is what you want:
public static interface Additive<T> {
default public Additive<T> crunch(Additive<T> other) { return null; }
}
public static class A implements Additive<A> {};
public static class B implements Additive<B> {};
public static class C implements Additive<C> {};
/**
* Takes a stream of arbitrary Additives and returns a Set containing
* only one crunched Additive for each type
*
* #param stream additives to crunch
* #return crunched set
*/
public Set<Additive<?>> crunch(Stream<Additive<?>> stream) {
return stream
.collect(Collectors.groupingBy(o -> o.getClass()))
.values().stream()
.map(values -> values.stream().reduce(Additive::crunch).get())
.collect(Collectors.toSet());
}
/**
* Takes a stream of arbitrary Additives and returns a Set containing
* only one crunched Additive for each type
*
* #param stream additives to crunch
* #return crunched set
*/
public Collection<Additive<Object>> crunchMap(Stream<Additive<?>> stream) {
return stream
.collect(Collectors.toMap(k -> k.getClass(), v -> (Additive<Object>) v, (a, b) -> a.crunch(b))).values();
}
Both method should produce the desired output. They take a Stream containing arbitrary Additives, group them by actual type, then crunch the ones of the same type into only one object, and finally return a Set or Collection containing only one object for each type of Additive.
I have laid out two different approaches. The first approach first groups into a map, and then crunches all similar types. this is perhaps the easier to understand method.
the second approach uses a mapping collector, mapping each additive to its class as key, and doing a no-op for the value, then, on a key collision, crunches the new value with the old values and puts that into the map. its a bit more involved, a bit harder to read and needs a bit more generic-fu to actually get to work.
Note that passing a Stream as parameter doesn't have any benefit - just pass the collection. In fact, passing streams is discouraged as you can never be sure who has already operated on the stream and who hasn't, leading to exceptions when the stream is already closed.
Note that I do not use your canCrunch method, but rely on the fact that each type can crunch itself and only itself, but no less. This is far easier to enforce and deal with than objects of same types not being able to be crushed. if you want that, you need some form to distinguish them and to change the classificator accordingly.
Given Calorie interface and implemented classes
// Interface that defines that item has calories and may be compared by it
interface Calorie extends Comparable<Calorie> {
public int compareTo(Calorie object);
public int getCalories();
}
// Examples of classes CaloryGrader is supposed to work with
class Drink implements Calorie {
// Some implemenation...
}
class Bakery implements Calorie {
// Some implementation...
}
class Cake extends Bakery {
// Some implementation...
}
## Given CaloryGrader class where I need to implement sorted static "grade" method ##
class CaloryGrader {
/**
* Returns sorted in ascending order copy of items list.
*
* Sort order is defined by item calories.
*
* #param items collection of items to sort
* #return sorted copy
*/
public List grade(List items) {
// Add implementation
}
}
The task is - to write grade by means of generics in order for it to sort only List of items which include Calories and its sublclasses.
I have written the following signature of grade method
public static <T extends Calorie> List<T> grade(List<T> items) {
Still, it does not work and I cannot figure out why.
T is a type of item which method can accept
List is a return type of a method
I assumed that argument List will restrict the List which can be passed to the method by only to all subclasses of Calories. But it is not correct right now.
I can create a list of raw type and pass it to the method. I assume it is due to the fact that it converts to List and it fits.
The resolution should be not to pass raw types to the method and receive a compile-time error. I guess I miss something.
You can use an Array for this hard constraint: grade(T[] items)
On top of that, an array backed List for quick conversion back & forth.
In JDK 8, java.util.Collection starts with
public interface Collection<E> extends Iterable<E> {
// Query Operations
/**
* Returns the number of elements in this collection. If this collection
* contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
* <tt>Integer.MAX_VALUE</tt>.
*
* #return the number of elements in this collection
*/
int size();
Interestingly, java.util.Set starts with
public interface Set<E> extends Collection<E> {
// Query Operations
/**
* Returns the number of elements in this set (its cardinality). If this
* set contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
* <tt>Integer.MAX_VALUE</tt>.
*
* #return the number of elements in this set (its cardinality)
*/
int size();
What is the purpose of overriding method declarations in interfaces? Why does not extends suffice?
EDIT java.util.List also shows redundancy, and the javadoc of List.size() is only minimally different that of Collection.size(), and does not introduce any new term:
public interface List<E> extends Collection<E> {
// Query Operations
/**
* Returns the number of elements in this list. If this list contains
* more than <tt>Integer.MAX_VALUE</tt> elements, returns
* <tt>Integer.MAX_VALUE</tt>.
*
* #return the number of elements in this list
*/
int size();
Overriding a method can be used for a lot of reasons besides to change the behavior. It can change the signature of the method (refining the return type with a covariant override), add annotations, broaden the accessibility (turning a protected method into public in a subclass), or refine the specification (expressed as Javadoc). In this case, the override exists so that the Set Javadoc could define the term "cardinality".
I have a hashmap called gg. I want to take out its keys using keySet() method and pass them as parameter of another method.
method_A( gg.keySet());
public void method_A(ArrayList<Integer> jj){
....
}
But I got this error:
error: incompatible types: Set<Integer> cannot be converted to ArrayList<Integer>.
Then I saw this:
method_A (new ArrayList<Integer>(gg.keySet()));
What is it doing actually ? It looks like type casting to me. I am puzzled. Could someone explain to me what is going on ?
new ArrayList<Integer>(gg.keySet()) is not type casting. It's more like a copy constructor (though actual copy constructors usually take an argument of the same type that is being instantiated, which is not the case here).
It's creating a new ArrayList<Integer> instance using the constructor that accepts a Collection as an argument. It adds all the elements found in the Collection to the new ArrayList.
Here's the doc of that constructor :
/**
* Constructs a list containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator.
*
* #param c the collection whose elements are to be placed into this list
* #throws NullPointerException if the specified collection is null
*/
public ArrayList(Collection<? extends E> c)
java.util.Map.Entry as I know is a public static interface in java.util package that
returns collection view of a map but as far now I am confused with the static interface
and as it is Map.Entry is it an inner interface if so how do we have inner static interfaces in java
The definition of Entry happens to live inside the definition of Map (allowed by java). Being static means you don't need an instance of Map to refer to an Entry.
It's easiest to show how to use Map.Entry by an example. Here's how you can iterate over a map
Map<Integer, String> map = new HashMap<Integer, String>();
for (Map.Entry<Integer, String> entry : map.entrySet()) {
Integer key = entry.getKey();
String value = entry.getValue();
// do something with key and/or value etc
// you may also alter the entry's value inside this loop via entry.setValue()
}
There isn't really anything to be confused about.
Yes, Java allows interfaces to be members of classes or other interfaces.
No, that does not mean anything special. It changes absolutely nothing about how you can use such an interface or what you can do with it.
It only changes the name of that interface and creates a strong conceptual link between it and its enclosing type. In this case, a Map.Entry represents an entry of a Map. The designers of the API apparently felt that it made sense to stress this connection by making it a member type.
Example:
public class Outer {
public interface Bar {
Bar get();
}
}
Bar is a nested interface. Nested interfaces are static by default, so you could as well write:
public class Outer {
public static interface Bar {
Bar get();
}
}
Now, what static in this context means is that the interface is a static member, i.e. a member of the class.
You can do this with classes as well:
public class Tree {
private static class Node {
}
}
Here, Node is even private, meaning it's only visible within Tree. So, what's the benefit of this? Why not make Node a public class? Because of better encapsulation. First, the Node is an implementation detail of the Tree, so you don't want it to be visible. Second, if you expose Node via a public API, some client (programmer) could use it in his code. Now, he has a hard dependency on this class. If at some point you want to change the representation of you Tree, and you change/remove the Node class, the client code's may break. And last but not least, your public API becomes smaller, which is also desirable.
So, when to use static member classes/interfaces? Mostly, if you build some sort of Composite object (like a Tree, or a Linked List) or when the class only makes sense in the context of the outer class.
Java allows nested interfaces. You can nest them into classes or interfaces. For instance, Map.Entry is a nested interface defined in the Map interface.
Map implementations (TreeMap, HashMap) provide private implementations of Map.Entry, which are not visible outside the class.
Bohemian's answer addresses how to use Map.Entry.
Yes, it's an inner interface of the Map interface.
/**
* A map entry (key-value pair). The <tt>Map.entrySet</tt> method returns
* a collection-view of the map, whose elements are of this class. The
* <i>only</i> way to obtain a reference to a map entry is from the
* iterator of this collection-view. These <tt>Map.Entry</tt> objects are
* valid <i>only</i> for the duration of the iteration; more formally,
* the behavior of a map entry is undefined if the backing map has been
* modified after the entry was returned by the iterator, except through
* the <tt>setValue</tt> operation on the map entry.
*
* #see Map#entrySet()
* #since 1.2
*/
interface Entry<K,V> {
/**
* Returns the key corresponding to this entry.
*
* #return the key corresponding to this entry
* #throws IllegalStateException implementations may, but are not
* required to, throw this exception if the entry has been
* removed from the backing map.
*/
K getKey();
/**
* Returns the value corresponding to this entry. If the mapping
* has been removed from the backing map (by the iterator's
* <tt>remove</tt> operation), the results of this call are undefined.
*
* #return the value corresponding to this entry
* #throws IllegalStateException implementations may, but are not
* required to, throw this exception if the entry has been
* removed from the backing map.
*/
V getValue();
/**
* Replaces the value corresponding to this entry with the specified
* value (optional operation). (Writes through to the map.) The
* behavior of this call is undefined if the mapping has already been
* removed from the map (by the iterator's <tt>remove</tt> operation).
*
* #param value new value to be stored in this entry
* #return old value corresponding to the entry
* #throws UnsupportedOperationException if the <tt>put</tt> operation
* is not supported by the backing map
* #throws ClassCastException if the class of the specified value
* prevents it from being stored in the backing map
* #throws NullPointerException if the backing map does not permit
* null values, and the specified value is null
* #throws IllegalArgumentException if some property of this value
* prevents it from being stored in the backing map
* #throws IllegalStateException implementations may, but are not
* required to, throw this exception if the entry has been
* removed from the backing map.
*/
V setValue(V value);
/**
* Compares the specified object with this entry for equality.
* Returns <tt>true</tt> if the given object is also a map entry and
* the two entries represent the same mapping. More formally, two
* entries <tt>e1</tt> and <tt>e2</tt> represent the same mapping
* if<pre>
* (e1.getKey()==null ?
* e2.getKey()==null : e1.getKey().equals(e2.getKey())) &&
* (e1.getValue()==null ?
* e2.getValue()==null : e1.getValue().equals(e2.getValue()))
* </pre>
* This ensures that the <tt>equals</tt> method works properly across
* different implementations of the <tt>Map.Entry</tt> interface.
*
* #param o object to be compared for equality with this map entry
* #return <tt>true</tt> if the specified object is equal to this map
* entry
*/
boolean equals(Object o);
/**
* Returns the hash code value for this map entry. The hash code
* of a map entry <tt>e</tt> is defined to be: <pre>
* (e.getKey()==null ? 0 : e.getKey().hashCode()) ^
* (e.getValue()==null ? 0 : e.getValue().hashCode())
* </pre>
* This ensures that <tt>e1.equals(e2)</tt> implies that
* <tt>e1.hashCode()==e2.hashCode()</tt> for any two Entries
* <tt>e1</tt> and <tt>e2</tt>, as required by the general
* contract of <tt>Object.hashCode</tt>.
*
* #return the hash code value for this map entry
* #see Object#hashCode()
* #see Object#equals(Object)
* #see #equals(Object)
*/
int hashCode();
}
For more information about interfaces, see the Interfaces tutorial and this Static Nested Interfaces article.
Inner interfaces are implicitly public and static.
You can have inner interfaces as follows :
1. interface A {
.....
.....
interface B {
....
....
}
}
2. class A {
....
....
interface B {
....
....
}
}
You can access the above inner interface(B) by A.B where A is a class or an interface according to the above two cases.
For example,
class x implements A.B
{
....
....
}