Implementing a functional interface via method reference - java

First I got a class named after my Chinese name
public class Yxj<T> {
private T[] data;
private int size = 0;
private final Comparator<? super T> comparator;
public Yxj(Comparator<? super T> c) {
data= (T[]) new Object[16];
comparator = c;
}
public void addItem(T t){
data[size++] = t;
}
public int sort(){
return comparator.compare(data[0], data[1]);
}
public T[] getData(){
return data;
}
}
in which a Comparator resides,then I defined a Norwich keeping a field order and setter and getter of it, finally there's a method used to implement the compare(T t1,T t2) in Comparator.
public class Norwich {
private int order;
public Norwich(int o) {
order = o;
}
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
public int compareOrder(Norwich n) {
if (order > n.getOrder()) {
return 2;
} else if (order == n.getOrder()) {
return 0;
} else {
return -3;
}
}
}
then here comes the main method
Yxj<Norwich> norwichYxj = new Yxj<>(Norwich::compareOrder);
norwichYxj.addItem(new Norwich(9));
norwichYxj.addItem(new Norwich(1));
System.out.println(norwichYxj.sort());
so what I'm interested in is that, why does not the method compareOrder keep the same parameters as the compare in Comparator but it can still work correctly?

It is simple. You have passed through the constructor your implementation of the Comparator to be used for comparing.
Yxj<Norwich> norwichYxj = new Yxj<>(Norwich::compareOrder);
Remember Comparator is nothing else than an interface. Since it is a functional interface, it can be represented through a lambda expression or a
method reference (as you did). The way you can pass the Comparator in the full form is as follows. Note the usage of the compareOrder method:
Yxj<Norwich> norwichYxj = new Yxj<>(new Comparator<>() {
#Override
public int compare(Norwich o1, Norwich o2) {
return o1.compareOrder(o2); // usage of compareOrder
}
});
This can be shortened to a lambda expression:
Yxj<Norwich> norwichYxj = new Yxj<>((o1, o2) -> o1.compareOrder(o2));
It can be shortened again to a method reference:
Yxj<Norwich> norwichYxj = new Yxj<>(Norwich::compareOrder);
Now you can see it can be represented in this way though the method compareOrder accepts only one formal parameter. The first parameter of the Comparator#compare method is the one invoking the compareOrder method and the second parameter is the one being passed to the compareOrder method.
Learn more here: https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html
Additionally, the classes you have constructed look a bit odd. Though the other answer doesn't in fact answer your question, it can lead you to a better code: Implementing a functional interface via method reference

class Yxj
The paramter T of your class Yxj should have more restrictions if you want to compare/sort in this class with T then say T must be comparable.
If your T array grows then don't implement your own growing array but use ArrayList instead which does that for you
If you do the first you don't need the Comperator anymore
Your methode sort only sorts the first and second element so you will get problems. If the data is shorter you will get an ArrayIndexOutOfBoundsException if it is longer it won't sort the rest of elements. So with a Collection you could simple use Collections.sort(data);
public class Yxj<T extends Comparable<T>> {
private final List<T> data;
public Yxj() {
this.data = new ArrayList<>();
}
public void addItem(T t){
data.add(t);
}
public void sort(){
Collections.sort(data);
}
public List<T> getData(){
return data;
}
public void print(){
System.out.println(data);
}
}
class Norwich
If you done the above know your Norwich class must implement the Comparable interface so you can compare Norwich instances with the methode compareTo which also will be called each time you or the API ask directly or indirectly to compare to Norwich instances like for sorting ect.
public class Norwich implements Comparable<Norwich> {
private int order;
public Norwich(int o) {
this.order = o;
}
public int getOrder() {
return this.order;
}
public void setOrder(int order) {
this.order = order;
}
#Override
public int compareTo(Norwich other) {
return this.order - other.order;
}
#Override
public String toString() {
return "Norwich{" +
"order=" + order +
'}';
}
}
Main
Done? Perfect, then your main could be looks like this
public static void main(String[] args) {
Yxj<Norwich> norwichYxj = new Yxj<>();
norwichYxj.addItem(new Norwich(9));
norwichYxj.addItem(new Norwich(1));
norwichYxj.sort();
norwichYxj.print();
}

Related

Use Comparable Interface to Sort a Generic Linked List

I want to sort my self implemented Linked List Using Comparable Interface with Java .I need to implement the compareTo method :
Here is the code for my class ListElement :
public class ListElement implements Comparable<ListElement> {
public Object wert;
public ListElement nachFolger;
public ListElement(Object wert , ListElement nachFolger) {
this.wert=wert;
this.nachFolger=nachFolger;
}
#Override
public int compareTo(ListElement a) {
if(this.nachFolger.wert - a.wert) {
return 1;
}
return 0;
}
}
But I get an error , any recommendations ?
You are trying to subtract to references of type Object.
Your element type should implement Comparable:
public class ListElement<T extends Comparable<T>> implements Comparable<ListElement<T>> {
public T wert;
public ListElement<T> nachFolger;
public ListElement(T wert, ListElement<T> nachFolger) {
this.wert=wert;
this.nachFolger=nachFolger;
}
#Override
public int compareTo(ListElement<T> a) {
return wert.compareTo(a.wert);
}
}
In Java, subtract operation only applies to numeric literals (and auto-unboxed numeric objects). As you are trying to use it on non numeric Object type, you are getting the error. If you want to compare two wert values, you can do the following:
Change the type to number from Object so that you can compare, e.g.:
public Object wert;
#Override
public int compareTo(ListElement a) {
return wert.compareTo(a.wert);
}
Change the type to Comparable so you can use compareTo on two wert objects
public Comparable wert;
#Override
public int compareTo(ListElement a) {
return wert.compareTo(a.wert);
}

How to bypass Java not being able to extend from multiple classes

I think I have a design problem in my Java app, but I cannot figure out how to solve or bypass it.
Say I have an interface and an abstract class implementing it as follows:
public interface IntegerCollection extends Collection<Integer> {
public int sum();
}
public abstract class AbstractIntegerCollection
extends AbstractCollection<Integer> implements IntegerCollection {
public int sum() {
// fancy code to calculate the sum of all collection members (just an example)
}
}
Now I would want to make this class instantiable by using the existing implementations of Collection (e.g., LinkedList); something like this:
public class IntegerLinkedList extends AbstractIntegerCollection, LinkedList<Integer> {
}
IntegerCollection ic = new IntegerLinkedList();
However, this does not work because Java does not support extending several classes. Also it looks quite ugly to me, as there is a mixture of hierarchies.
Of course, I could let IntegerLinkedList implement IntegerCollection instead of letting it extend AbstractIntegerCollection. But then, I would have to repeat the code for sum() in all other implementations (e.g., IntegerArrayList).
Is there a better way to do this?
I'm not sure what exactly, you are trying to achieve, but rather you could implements List instead of extending LinkedList
public class IntegerLinkedList
extends AbstractIntegerCollection
implements List<Integer>
{
}
But, you need to implements all abstract method of List.
Since java 8 it has been possible to include implementations in an interface by using the default keyword. Therefore you don't need AbstractIntegerCollection - all the common code can be put in the interface. Here is an example:
import java.util.Collection;
import java.util.LinkedList;
public class Main {
interface IntegerCollection extends Collection<Integer> {
default int sum() {
int sum = 0;
for (int a : this)
sum += a;
return sum;
}
}
static class IntegerLinkedList extends LinkedList<Integer> implements IntegerCollection {
}
public static void main(String[] args) {
IntegerCollection list = new IntegerLinkedList();
list.add(1);
list.add(2);
list.add(3);
System.out.println(list.sum()); // Prints 6
}
}
This works, but I'm not sure it's a good idea. I'd think very carefully before extending a class like LinkedList. Some people also consider it an anti-pattern to extend generic classes with non-generic ones.
Another thing to be aware of is that it is not possible to write default methods for the methods of Object like equals and toString etc.
Since you are using Java 7, the above solution is not available. However, with a load of tedious forwarding methods, you can do it using composition rather than inheritance. Josh Bloch's book Effective Java gives a very good explanation of why composition is preferable anyway. Here is an (incomplete) example - you'll need to add a few more forwarding methods to avoid UnsupportedOperationExceptions when you try doing other things with the list.
import java.util.*;
public class Main {
abstract static class AbstractIntegerCollection extends AbstractCollection<Integer> {
public int sum() {
int sum = 0;
for (int a : this)
sum += a;
return sum;
}
}
static class IntegerLinkedList extends AbstractIntegerCollection implements List<Integer> {
private final List<Integer> list = new LinkedList<>();
#Override
public Iterator<Integer> iterator() {
return list.iterator();
}
#Override
public int size() {
return list.size();
}
#Override
public boolean addAll(int index, Collection<? extends Integer> c) {
return list.addAll(index, c);
}
#Override
public Integer get(int index) {
return list.get(index);
}
#Override
public Integer set(int index, Integer element) {
return list.set(index, element);
}
#Override
public boolean add(Integer element) {
return list.add(element);
}
#Override
public void add(int index, Integer element) {
list.add(index, element);
}
#Override
public Integer remove(int index) {
return list.remove(index);
}
#Override
public int indexOf(Object o) {
return list.indexOf(o);
}
#Override
public int lastIndexOf(Object o) {
return list.lastIndexOf(o);
}
#Override
public ListIterator<Integer> listIterator() {
return list.listIterator();
}
#Override
public ListIterator<Integer> listIterator(int index) {
return list.listIterator(index);
}
#Override
public List<Integer> subList(int fromIndex, int toIndex) {
return list.subList(fromIndex, toIndex);
}
// More of these
}
public static void main(String[] args) {
IntegerLinkedList list = new IntegerLinkedList();
list.add(1);
list.add(2);
list.add(3);
System.out.println(list.sum()); // Prints 6
}
}
This solution is far from perfect. For one thing, it would be better if IntegerLinkedList extended AbstractList<Integer> rather than just AbstractCollection<Integer>, but then you couldn't extend AbstractIntegerCollection too.

Java generics and casting to a primitive type

I am currently trying to learn how to use Generics from a book. In this chapter it says to take a piece of data T and convert it to an integer. I am trying different things in Eclipse, but none of them seem to allow this. How could you perform the following task:
LinkedList<T> arr = new LinkedList<T>();
Float fl = 8.74273123948;
arr.add(fl);
Then in another class:
public int findValue(Node node)
{
T data = node.data;
int value = Number.valueOf(data);
return value;
}
I have tried using .valueOf() and (int) among a few other things and nothing seems to satiate Java. The book insists on keeping the method generic in case floats or doubles were used instead of strings or ints.
EDIT: For other people that might have a similar question. Gleaned from all the comments to this question and the answer that was accepted:
use the .toString() on the data and then parse it as you need to whichever data type you need.
Hmm, that is an odd book. I'll try to tell you the gist of it based on what I know.
Generics are a construct that allow you compile-time check of whether a type you are trying to use in a specific collection, method, or class is actually something that knows the functionality that is necessary for that specific thing to function.
For example, you need to use the function determined by the interface called SearchParameter in your template, but you only see the <T> parameter as an object. Or maybe a better example in your case would be a custom interface called IntegerConvert like so:
public interface IntegerConvert
{
Integer returnAsInteger();
}
And you could have a class like this:
public class MyData implements IntegerConvert
{
private String data;
public MyData(String data)
{
this.data = data;
}
#Override
public Integer returnAsInteger()
{
return Integer.parseInt(data); //throws ParseException if it doesn't work
}
}
And then you could have a List of these like this:
List<IntegerConvert> listOfConvertibles = new ArrayList<IntegerConvert>();
or if you want to go a bit more generic for the future,
List<? extends IntegerConvert> listOfConvertibles = new ArrayList<IntegerConvert>();
and then you can do
listOfConvertibles.add("25");
listOfConvertibles.add("40");
listOfConvertibles.add("35");
for(IntegerConvert ic : listOfConvertibles)
{
System.out.println("" + ic.returnAsInteger());
}
Although that was a bit of an overcomplicated example, I guess. A simpler example would be the following:
public class Node<E>
{
private E data;
public Node(E e)
{
this.data = e;
}
public E getData()
{
return data;
}
public void setData(E e)
{
data = e;
}
public void print()
{
System.out.println(data.toString());
}
}
public class MyClass
{
public void doSomething()
{
List<Node<Float>> listOfFloatNodes = new ArrayList<Node<Float>>();
listOfFloatNodes.add(new Node<Float>(new Float(8.7472742f)));
listOfFloatNodes.add(new Node<Float>(new Float(5.56842742f)));
listOfFloatNodes.add(new Node<Float>(new Float(6.5467742f)));
MyOtherClass moc = new MyOtherClass();
moc.useNodeList(listOfFloatNodes);
}
}
public class MyOtherClass
{
public <E> void useNodeList(List<Node<E>> list)
{
for(Node<E> node : list)
{
printNode(node);
}
}
public <E> void printNode(Node<E> node)
{
node.print();
}
}
public class MainClass
{
public static void main(String[] args)
{
MyClass myClass = new MyClass();
myClass.doSomething();
}
}
If you have any questions, comment.
try to observe below examples:
public static void main(String[] args) {
test0("13");
test0(new Integer(13));
test1();
System.out.println(findValue(new Node("10")));
}
private static <T> void test0(T a) {
LinkedList<T> arr = new LinkedList<T>();
arr.add((T) a);
System.out.println(arr.getFirst());
}
private static <T> void test1() {
LinkedList<T> arr = new LinkedList<T>();
arr.add((T) new Integer(13));
System.out.println(arr.getFirst());
}
public static <T> int findValue(Node node) {
T data = (T) node.data;
int value = Integer.valueOf(data.toString());
return value;
}
where Node is :
public class Node {
//this should be private
public String data;
public Node(String data) {
this.data = data;
}
//use getter below to access private data
public String getData() {
return data;
}
}
all this is possible because, unchecked casts from a known type to T is allowed (of course with warnings) and compiler believes you for the casting.
Answer not entirely on the topic albeit closely related. I had a problem and didn't find the answer. Then I found solution and thought I'd share:
I was trying to cast generic value to primitive type:
<TYPE> boolean equal(TYPE val, Class<?> type) {
if (float.class == type) {
float val2 = (float) val; // incompatible types: TYPE cannot be converted to float
float val3 = (float) (Object) val; // works
...
Long story short: first version doesn't work and the second does. Quite annoying.

Java sort through 3 classes

how can I sort Event by index?
simple view of my project:
class Event{
int index;
}
class EventField{
Event[] field;
}
class Action{
EventField ev;
ev.sort(); // Sort event in field EventField by index
}
Use Arrays.sort() with Comparator<Event> which is using Integer.compare()
Arrays.sort(ev.field, new Comparator<Event>(){
#Override
public int compare(Event e1, Event e2) {
return Integer.compare(e1.index, e2.index)
}
});
You need to implement method in EventField
class EventField{
Event[] field;
public void sort(){ Arrays.sort(field, yourCustomComparatorInstance }
}
that does sorting using a custom Comparator on Event
Related:
Sorting a list of points with Java
See
Arrays.sort()
In java you have 2 ways to define order you can create a Comparator for creating your sort strategy, or define natural-order of your class implementing Comparable
Example using Comparator:
class Event{
private int index;
public static final Comparator<Event> INDEX_COMPARATOR = new MyComparator();
//TODO define getters and setter equals & hashCode cause it's strong recommended
static class MyComparator implements Comparator<MyClass>{
#Override
public int compare(Event o1, Event o2) {
return Integer.valueOf(o1.index).compareTo(o2.index);
}
}
}
And then in EventField.
Example:
class EventField{
Event[] fields;
public void sort(){
Arrays.sort(fields,Event.INDEX_COMPARATOR );
}
}
Read more : Collections#sort(..)
If you want to define natural-ordering of your class just define
public class Event implements Comparable<Event>{
private int index;
//define getter&setter & recommended equals & hashCode
#Override
public int compareTo(Event o) {
return Integer.valueOf(index).compareTo(o.index);
}
}
And in EventField code:
Arrays.sort(fields); // where fields is Event[]
If events are naturally something you'll be comparing a lot in your program, you can extend the Comparable interface:
public class Event implements Comparable<Event> {
private int index;
public int getIndex() {
return index;
}
#Override
public int compareTo(Event o) {
return index == o.getIndex() ? 0 : (index > o.getIndex() ? 1 : -1);
}
}
Then you can call Arrays.sort(ev.getField()). If the objects in 'field' are always going to be sorted, then you can just keep its objects sorted whenever you add something to it.

How to add listener on ArrayList in java

I want to create my own implementation of ArrayList in java, that can listen when the list is changing and to do action when this happens.
From what I have read, I understand that I can't extend ArrayList and then add listener.
I want to use MyList in class as a variable with public modifier, so users can change it directly and to be done action when he changes it.
class MyList extends ArrayList<object>.... { ... }
class UseOfMyList {
public MyList places = new MyList<Object>();
places.add("Buenos Aires");
//and to be able to do that
List cities = new ArrayList<Object>();
cities.add("Belmopan");
places = cities;
So how to create and when do add,remove or pass another list to MyList an action to be performed?
You're not going to be able to do this by extending ArrayList, as it has no built-in notification mechanism (and, further, because it is has been declared final and thus cannot be extended). However, you can achieve your desired result by creating your own List implementation and adding your "listener" functionality vis a vis the add() and remove() methods:
class MyList<T>{
private ArrayList<T> list;
public MyList(){
list = new ArrayList<>();
...
}
public void add(T t){
list.add(t)
//do other things you want to do when items are added
}
public T remove(T t){
list.remove(t);
//do other things you want to do when items are removed
}
}
Old question, I know.
I apologize in advance for any bad formatting or missing lines of code. I'm a long-time user, first time contributor.
Anyhow, because of the removal of JavaFX from the JDK11, I was forced to write my own version of the ObservableList. Sure, we can plop JavaFX in with JMods or Maven, but it seems like a bit of an overkill just for the FXCollections.
Long Story made Short...er :)
I started out reading this old question and the answer didn't suit my needs fully, so I've added a custom event/listener class.
Figured I could share since this site has improved my coding 10 fold.
public static void main(String[] args) {
BackedList<String> list = new BackedList();
list.addListener(new BackedListListener<String>(){
#Override
public void setOnChanged(ListChangeEvent<String> event) {
if (event.wasAdded()) {
event.getChangeList().forEach(e->{
// do whatever you need to do
System.out.println("added: " + e);
});
}
if (event.wasRemoved()) {
// do whatever you need to dl
event.getChangeList().forEach(e->{System.out.println(e + " was removed");});
}
}
});
Class: BackedObservableList
public class BackedObservableList<T> implements List<T> {
private final List<T> backed;
public BackedObservableList() {
backed = new ArrayList();
}
public BackedObservableList(List<T> backed) {
this.backed = backed;
}
/*
You will want to override every method. For any method that performs an add/remove
operation, you will have to do some coding / testing. I'll do an add() op, a remove()
op, and an interator in this example. Anything that is not an add/remove op, you can straight up delegate it to the underlying list.
Also remember that list.clear() is a removal operation, where you can simply iterate through the backed list and call the overide remove(T t) method, or just plop the whole backed list into the ListChangeEvent<T> class and delegate to the backed array again.
*/
#Override
public boolean add(T e) {
if (backed.add(e)) {
ListChangeEvent<T> event = new ListChangeEvent(this, backed.indexOf(e), backed.indexOf(e) + 1, true, e);
notifyListeners(event);
return true;
}
return false;
}
}
#Override
public boolean remove(Object o) {
if (backed.remove(o)) {
ListChangeEvent<T> event = new ListChangeEvent(this, backed.indexOf(o),
backed.indexOf(o) + 1, false, o);
notifyListeners(event);
return true;
}
return false;
}
/*
The iterator seemed easy enough, until I remembered the iterator.remove() call.
I still haven't fully tested it (it works, but only as far as I've used it)
*/
#Override
public Iterator<T> iterator() {
return new Iterator<T>() {
T currentItem = null;
int currentIndex = 0;
#Override
public boolean hasNext() {
return backed.size() > currentIndex;
}
#Override
public T next() {
return currentItem = backed.get(currentIndex++);
}
#Override
public void remove() {
if (backed.remove(currentItem)) {
currentIndex--;
notifyListeners(new ListChangeEvent<T>(backed, currentIndex, currentIndex + 1, false, currentItem));
}
}
};
}
private void notifyListeners(ListChangeEvent<T> event) {
for (BackedListListener<T> listener : listeners) {
listener.setOnChanged(event);
}
}
private final List<BackedListListener> listeners = new ArrayList();
public void addListener(BackedListListener<T> listener) {
listeners.add(listener);
}
Class: ListChangeEvent
It simply provides a reference to the backed list (which you may want to wrap with Collections.unmodifiableList()
public class ListChangeEvent<T> {
private final List<T> source;
private final List<T> changeList;
private final boolean wasAdded;
private final int to, from;
public ListChangeEvent(List<T> source, int from, int to, boolean wasAdded, T... changeItems) {
this(source, from, to, wasAdded, Arrays.asList(changeItems));
}
public ListChangeEvent(List<T> source, int from, int to, boolean wasAdded, List<T> changeItems) {
this.source = source;
this.changeList = changeItems;
this.wasAdded = wasAdded;
this.to = to;
this.from = from;
}
public int getFrom() {
return from;
}
public int getTo() {
return to;
}
public List<T> getSource() {
return source;
}
public List<T> getChangeList() {
return changeList;
}
public boolean wasAdded() {
return wasAdded;
}
public boolean wasRemoved() {
return !wasAdded;
}
}
Class: BackedListListener
/*
Finally a little functional interface... or, because I was too lazy to change it to one, a simple one-liner abstract class with some generics
*/
public abstract class BackedListListener<T> {
public abstract void setOnChanged(ListChangeEvent<T> event);
}
the resp. ;)
private class MyList extends ArrayList<Objects> {
#Override
public void sort(Comparator c) {
super.sort(c);
resetLancamentos(); // call some metod ;)
}
//...
#Override
public boolean removeAll(Collection c) {
//To change body of generated methods, choose Tools | Templates.
boolean ret = super.removeAll(c);
resetLancamentos(); // some metod like fireObjChanged() will do the job too
return ret;
}
}

Categories

Resources