I'm quite new to Java so this is probably pretty straight forward question.
I want to sort an ArrayList in the class MediaLib based on the natural order of a specified key.
I can't work out how to use my comparator (compareTo(MediaInterface, key)) which is in the Media class. Whats the best way to go about this?
package assign1;
import java.util.*;
public class Media implements MediaInterface {
private Map<String, Object> fields;
private static int compare;
public Media(String title, String format) {
fields = new TreeMap<String, Object>();
fields.put("title", title);
fields.put("format", format);
}
public Object get(String key) {
return fields.get(key);
}
public void put(String key, Object value) {
fields.put(key, value);
}
public boolean hasKeywords(String[] words, boolean combineWithAND) {
Collection<Object> values = (Collection<Object>) fields.values();
int count = 0;
int size = 0;
for (String s: words) {
for (Object o: values) {
String t = o.toString();
if (t.indexOf(s) >= 0) {
count++;
break;
}
}
size++;
}
if ((count == 0 && !combineWithAND) || (combineWithAND && (count != size))) {
return false;
}
return true;
}
public int compareTo(MediaInterface mi, String key) { //<<<<<<<------calling this!!
if (mi == null)
throw new NullPointerException();
Media m = (Media) mi;
Comparable mValue = (Comparable) m.get(key);
Comparable lValue = (Comparable) fields.get(key);
if ((mValue == null) && (lValue == null)){
return 0;
}
if ((lValue == null)){
return 1;
}
if ((mValue == null)){
return -1;
}
return (lValue).compareTo(mValue);
}
#Override
public int compareTo(MediaInterface mi) {
if (mi == null)
throw new NullPointerException();
Media m = (Media) mi;
Set<String> lSet = fields.keySet();
if (compareTo(m, "title") != 0) {
return compareTo(m, "title");
}
if (compareTo(m, "year") != 0) {
return compareTo(m, "year");
}
for (String s: lSet) {
if (compareTo(m, s) != 0) {
return compareTo(m, s);
}
}
return 0;
}
public boolean equals(Object object) {
if (object == null)
return false;
if (!(object instanceof Media))
return false;
Media m = (Media) object;
if (compareTo(m) != 0) {
return false;
}
return true;
}
}
package assign1;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
public class MediaLib implements Searchable {
private ArrayList<MediaInterface> media;
public MediaLib() {
media = new ArrayList<MediaInterface>();
}
#Override
public void add(MediaInterface mi) {
if (media.isEmpty()) {
media.add(mi);
}
else {
for (MediaInterface m: media) {
if (mi.equals(m)) {
return;
}
}
media.add(mi);
}
}
#Override
public boolean contains(MediaInterface mi) {
for (MediaInterface m: media) {
if (mi.equals(m)) {
return true;
}
}
return false;
}
#Override
public Collection<MediaInterface> findByKeyword(String[] words, boolean combineWithAND) {
Collection<MediaInterface> foundList = new ArrayList<MediaInterface>();
for (MediaInterface mi: media) {
if (mi.hasKeywords(words, combineWithAND)) {
foundList.add(mi);
}
}
return foundList;
}
#Override
public Collection<MediaInterface> findByTitle(String str) {
Collection<MediaInterface> foundList = new ArrayList<MediaInterface>();
for (MediaInterface mi: media) {
if ((mi.get("title")).equals(str)) {
foundList.add(mi);
}
}
return foundList;
}
#Override
public Collection<MediaInterface> getAllWithFormat(String formatName) {
Collection<MediaInterface> foundList = new ArrayList<MediaInterface>();
for (MediaInterface mi: media) {
if ((mi.get("format")).equals(formatName)) {
foundList.add(mi);
}
}
return foundList;
}
public Collection<MediaInterface> getAll() {
Collection<MediaInterface> fullList = new ArrayList<MediaInterface>();
for (MediaInterface mi: media) {
fullList.add(mi);
}
return fullList;
}
#Override
public void removeAllWithKeyword(String[] words, boolean combineWithAND) {
Collection<MediaInterface> foundList = findByKeyword(words, combineWithAND);
for (MediaInterface mi: foundList) {
media.remove(mi);
}
}
#Override
public void removeAllWithFormat(String format) {
Collection<MediaInterface> foundList = getAllWithFormat(format);
for (MediaInterface mi: foundList) {
media.remove(mi);
}
}
#Override
public void sort() {
Collections.sort(media);
}
#Override
public void sort(final String fieldName) {
Collections.sort(media, new Media.compareTo(MediaInterface, fieldName)) //<<<<<--------Trying to call compareTo()
}
}
public void parse(java.io.BufferedReader br) throws java.io.IOException {
while(br.readLine()!= null) {
Media mi = new Media(/n br.readLine(), br.readLine());
while
}
}
}
You already implement the Comparable interface in your MediaInterface class, this is a generic interface, so you then implement Comparable<MediaInterface> which will then require you to implement a method with the signature
public int compareTo(final MediaInterface other)
This is why your call to Collections.sort(media); compiles
In order to sort by a specific field name, you need to provide an instance of a Comparator, the easiest way to do this will be to create an inner class in your Media class which you can then pass into Collections.sort. For example
public class Media implements MediaInterface {
public static final class FieldComparator implements Comparator<Media> {
private final String field;
public FieldComparator(final String field) {
this.field = field;
}
public int compare(final Media a, final Media b) {
// implementation to compare a.field to b.field
}
}
}
You can then rewrite your second sort method as
#Override
public void sort(final String fieldName) {
Collections.sort(media, new Media.FieldComparator(fieldName));
}
Related
I need to create a vector class that implements the Map interface, but in the put method it returns NullException, I need help implementing the put method, I can't find this type of content on the internet
public class Vetor_map implements Map<Key, Student> {
private int nElements;
private Map<Key, Student> mapa[];
public Vetor_map(int max) {
mapa = new Map[max];
nElements = 0;
}
// PUT
#Override
public Estudante put(Key key, Estudants value) {
if (!isFull()) {
mapa[nElements].put(key, value);
nElements++;
return value;
}
return value;
}
public boolean isEmpty() {
// TODO Auto-generated method stub
if (nElements == 0)
return true;
return false;
}
public boolean isFull() {
if (nElements == mapa.length) {
return true;
}
return false;
}
Class main:
public static void main(String[] args) {
// TODO Auto-generated method stub
Key ch = new Key();
Student es = new Student();
Vetor_map vm = new Vetor_map(10);
System.out.println("Key: " + ch + ", Estudant: "+ es);
vm.put(ch, es);
Error
A Map is a collection of entries where each entry is a key-value pair. So your Vetor_map class should implement java.util.Map – which it does – but I think that you should also create a class that implements interface Map.Entry.
In the below code, I added an inner class VectorMapEntry that implements Map.Entry and therefore class VectorMap – which implements interface Map – contains an array of VectorMapEntry instances. From there it is just a simple matter of implementing the methods of both interfaces, namely Map and Map.Entry.
Note the following in the below code.
I changed the name from Vetor_map to VectorMap.
I added methods toString() and main() to class VectorMap for testing purposes only. I also added method toString() to classes Key and Student also for testing purposes.
You did not supply code for classes Key and Student so I added skeleton definitions for those two classes. Note that each class – Key and Student – must each implement method equals. I only added method hashCode since the javadoc for method equals() recommends doing so.
VectorMap cannot contain a null Key but it can contain a null Student as a value for a given Key.
Each Key in VectorMap is unique. When calling method put() with a Key that already exists in VectorMap, the existing value is replaced.
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class VectorMap implements Map<Key, Student> {
private static class VectorMapEntry implements Map.Entry<Key, Student> {
private Key key;
private Student student;
public VectorMapEntry(Key k, Student s) {
key = k;
student = s;
}
public Key getKey() {
return key;
}
public Student getStudent() {
return student;
}
public void setStudent(Student s) {
student = s;
}
#Override
public Student getValue() {
return student;
}
#Override
public Student setValue(Student value) {
student = value;
return value;
}
}
private int nElements;
private VectorMapEntry[] entries;
public VectorMap(int initialSize) {
if (initialSize <= 0) {
throw new IllegalArgumentException("Initial size must be positive.");
}
entries = new VectorMapEntry[initialSize];
}
#Override
public int size() {
return nElements;
}
#Override
public boolean isEmpty() {
return nElements == 0;
}
#Override
public boolean containsKey(Object key) {
boolean found = false;
for (VectorMapEntry entry : entries) {
if (entry == null) {
break;
}
found = entry.getKey().equals(key);
if (found) {
break;
}
}
return found;
}
#Override
public boolean containsValue(Object value) {
boolean found = false;
for (VectorMapEntry entry : entries) {
if (entry == null) {
break;
}
found = entry.getStudent().equals(value);
if (found) {
break;
}
}
return found;
}
#Override
public Student get(Object key) {
for (VectorMapEntry entry : entries) {
if (entry == null) {
break;
}
if (entry.getKey().equals(key)) {
return entry.getStudent();
}
}
return null;
}
#Override
public Student put(Key key, Student value) {
if (key == null) {
throw new IllegalArgumentException("Null key.");
}
boolean found = false;
for (VectorMapEntry entry : entries) {
if (entry == null) {
break;
}
if (entry.getKey().equals(key)) {
entry.setStudent(value);
found = true;
break;
}
}
if (!found) {
if (nElements == entries.length) {
throw new RuntimeException("Map is full.");
}
entries[nElements] = new VectorMapEntry(key, value);
nElements++;
}
return value;
}
#Override
public Student remove(Object key) {
int index = 0;
Student s = null;
for (VectorMapEntry entry : entries) {
if (entry == null) {
break;
}
if (entry.getKey().equals(key)) {
s = entry.getStudent();
break;
}
index++;
}
if (index < nElements) {
for (int i = index; i < nElements - 1; i++) {
entries[i] = entries[i + 1];
}
nElements--;
}
return s;
}
#Override
public void putAll(Map<? extends Key, ? extends Student> m) {
if (m != null) {
m.entrySet()
.stream()
.forEach(ent -> put(ent.getKey(), ent.getValue()));
}
}
#Override
public void clear() {
for (int i = 0; i < nElements; i++) {
entries[i] = null;
}
nElements = 0;
}
#Override
public Set<Key> keySet() {
Set<Key> keySet = new HashSet<>();
for (int i = 0; i < nElements; i++) {
keySet.add(entries[i].getKey());
}
return keySet;
}
#Override
public Collection<Student> values() {
Collection<Student> vals = new ArrayList<>(nElements);
for (int i = 0; i < nElements; i++) {
vals.add(entries[i].getStudent());
}
return vals;
}
#Override
public Set<Map.Entry<Key, Student>> entrySet() {
Set<Map.Entry<Key, Student>> entSet = new HashSet<>();
for (int i = 0; i < nElements; i++) {
entSet.add(entries[i]);
}
return entSet;
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('[');
boolean first = true;
for (int i = 0; i < nElements; i++) {
if (first) {
first = false;
}
else {
sb.append(", ");
}
sb.append(entries[i].getKey());
sb.append('=');
sb.append(entries[i].getValue());
}
sb.append(']');
return sb.toString();
}
public static void main(String[] args) {
Key ch = new Key();
Student es = new Student();
VectorMap vm = new VectorMap(10);
System.out.println("Key: " + ch + ", Estudant: "+ es);
vm.put(ch, es);
System.out.println(vm);
}
}
class Key {
public boolean equals(Object obj) {
return false;
}
public int hashCode() {
return -1;
}
public String toString() {
return "Key";
}
}
class Student {
public boolean equals(Object obj) {
return false;
}
public int hashCode() {
return -1;
}
public String toString() {
return "Student";
}
}
Also note that it would be possible to change the above code such that VectorMap could (theoretically) contain an infinite number of key-value pairs. This could be achieved by simply enlarging the entries array whenever it gets completely filled.
I defined classes Graph containing GraphNode as follows, my intention for declaring N is to compare 2 GraphNode objects using generics.
The question is how shall I instantiate the Graph which is recursively bound.
error while declaring as below.
Graph<Integer,Comparable<GraphNode>> graph = new Graph<>();
Bound mismatch: The type Comparable<GraphNode> is not a valid substitute for the bounded parameter <N extends Comparable<GraphNode<T,N>>> of the type Graph<T,N>
public class Graph<T, N extends Comparable<GraphNode<T, N>>> {
private N root;
private Class<N> clazz;
Graph(Class<N> clazz) {
this.clazz = clazz;
}
public N getInstance() {
try {
return clazz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
return null;
} catch (IllegalAccessException e) {
e.printStackTrace();
return null;
}
}
#SuppressWarnings("unchecked")
public void insert(T d, N n) {
if (root == null && n == null)
root = getInstance();
if (root == null)
root = n;
N node = root;
while (node != null) {
if (node.equals(n)) {
N newNode = getInstance();
((GraphNode<T, N>) newNode).setAdjNode(newNode);
}
}
}
}
public class GraphNode<T, N extends Comparable<GraphNode<T, N>>> implements Comparable<N> {
private T data;
private LinkedHashSet<N> adjNodes = new LinkedHashSet<>();
GraphNode() {
data = null;
}
GraphNode(T d) {
setData(d);
}
public void setAdjNode(N n) {
adjNodes.add(n);
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
#Override
public int hashCode() {
return data.hashCode();
}
#Override
public boolean equals(Object obj) {
if (obj instanceof GraphNode<?, ?>) {
return ((GraphNode<?, ?>) obj).getData() == this.getData();
}
return false;
}
#Override
public String toString() {
return data + "";
}
#Override
public int compareTo(N o) {
return this.compareTo(o);
}
}
This solved my above problem
public class Graph<T extends Comparable<T>> {
private GraphNode<T> root;
public void insert(T d, GraphNode<T> n) {
if (root == null && n == null)
root = new GraphNode<T>(d);
if (root == null)
root = n;
GraphNode<T> node = root;
Queue<GraphNode<T>> queue = new ConcurrentLinkedQueue<>();
queue.add(root);
while (!queue.isEmpty()) {
node = queue.poll();
node.setNodeColor(color.BLACK);
if (node.equals(n)) {
GraphNode<T> newNode = new GraphNode<T>(d);
((GraphNode<T>) newNode).setAdjNode(newNode);
} else {
queue.addAll(node.getUnexploredAdjNodes());
}
}
}
}
public class GraphNode<T extends Comparable<T>> implements Comparable<GraphNode<T>> {
enum color {
WHITE, GREY, BLACK
};
private T data;
private color nodeColor = color.WHITE;
private LinkedHashSet<GraphNode<T>> adjNodes = new LinkedHashSet<>();
GraphNode() {
data = null;
}
GraphNode(T d) {
setData(d);
}
public void setAdjNode(GraphNode<T> n) {
adjNodes.add(n);
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public LinkedHashSet<GraphNode<T>> getAdjNodes() {
return adjNodes;
}
public LinkedHashSet<GraphNode<T>> getUnexploredAdjNodes() {
LinkedHashSet<GraphNode<T>> n = new LinkedHashSet<>();
for (GraphNode<T> node : adjNodes) {
if (node.getNodeColor() == color.WHITE)
n.add(node);
}
return n;
}
public color getNodeColor() {
return nodeColor;
}
public void setNodeColor(color nodeColor) {
this.nodeColor = nodeColor;
}
#Override
public int hashCode() {
return data.hashCode();
}
#Override
public boolean equals(Object obj) {
if (obj instanceof GraphNode<?>) {
return ((GraphNode<?>) obj).getData() == this.getData();
}
return false;
}
#Override
public int compareTo(GraphNode<T> o) {
return data.compareTo(o.data);
}
#Override
public String toString() {
return data + "";
}
}
Graph<Integer> graph = new Graph<>();
I have created a Custom JavaFX Control, Call it ComboBoxTablePopup, it's a Generic Control witch takes a list of items of type S from the user.
Internally, i have used some sort of filtering in the TableView(a child of ComboboxTablePopup Contrl).So i have used :
FiltredList.setPridcate(S -> {
if (pr == null || pr.isEmpty() || pr.length() == 0)
return true;
if (((Engine) S).getDesignation().toLowerCase().contains(pr.toLowerCase())) {
return true;
} else
return false;).
Because i'm using generic class and the list can be of any type i have to cast filtredlist items to well known object in ordre to get filtring work.
So, how can i make the predicate function generic, so i can work with any object and filtre it ?
Here is the code of my CustomControl:
public class ComboBoxTablePopup<S> extends ComboBoxBase {
private
ObservableList<TableColumn> columns = FXCollections.emptyObservableList();
public ObservableList<TableColumn> getColumns() {
return columns;
}
public void setColumns(ObservableList<TableColumn> columns) {
this.columns = columns;
}
/***************************************************************************
* *
* Static properties and methods *
* *
**************************************************************************/
private static <T> StringConverter<T> defaultStringConverter() {
return new StringConverter<T>() {
#Override
public String toString(T t) {
return t == null ? null : t.toString();
}
#Override
public T fromString(String string) {
return (T) string;
}
};
}
/***************************************************************************
* *
* Constructors *
* *
**************************************************************************/
/**
* Creates a default ComboboxTablePopup instance with an empty
* {#link #itemsProperty() items} list and default
* {#link #selectionModelProperty() selection model}.
*/
public ComboBoxTablePopup() {
this(FXCollections.<S>emptyObservableList());
}
/**
* Creates a default ComboboxTablePopup instance with the provided items list and
* a default {#link #selectionModelProperty() selection model}.
*/
public ComboBoxTablePopup(ObservableList<S> items) {
setItems(items);
getStyleClass().add(DEFAULT_STYLE_CLASS);
setEditable(true);
setPromptText("Plz Search for a pirticular term");
}
public ComboBoxTablePopup(ObservableList<S> items, ObservableList<TableColumn> columns) {
this(items);
this.columns = columns;
}
private static final String DEFAULT_STYLE_CLASS = "combobox-table-popup";
private ReadOnlyObjectWrapper<TextField> editor;
private ObjectProperty<ObservableList<S>> items = new SimpleObjectProperty<ObservableList<S>>(this, "items");
public final void setItems(ObservableList<S> value) {
itemsProperty().set(value);
}
public final ObservableList<S> getItems() {
return items.get();
}
public ObjectProperty<ObservableList<S>> itemsProperty() {
return items;
}
// Converter
public ObjectProperty<StringConverter<S>> converterProperty() {
return converter;
}
private ObjectProperty<StringConverter<S>> converter =
new SimpleObjectProperty<StringConverter<S>>(this, "converter", ComboBoxTablePopup.<S>defaultStringConverter());
public final void setConverter(StringConverter<S> value) {
converterProperty().set(value);
}
public final StringConverter<S> getConverter() {
return converterProperty().get();
}// Create a symmetric (format/parse) converter with the default locale.
// Editor
public TextField getEditor() {
return editorProperty().get();
}
public ReadOnlyObjectProperty<TextField> editorProperty() {
if (editor == null) {
editor = new ReadOnlyObjectWrapper<TextField>(this, "editor");
editor.set(new ComboBoxListViewSkin.FakeFocusTextField());
}
return editor.getReadOnlyProperty();
}
#Override
protected Skin<?> createDefaultSkin() {
return new ComboBoxTablePopupSkin<>(this);
}
}
public class ComboBoxTablePopupSkin<S> extends ComboBoxPopupControl {
private ComboBoxTablePopup comboBoxTablePopup;
private ObservableList<S> comboboxTablePopupItems;
private TextField displayNode;
private TableView<S> tableViewPopupContent;
FilteredList<S> filtredList;
private SortedList<S> sortedList;
private Predicate<S> predicate;
private final InvalidationListener itemsObserver;
private final ListChangeListener<S> tableViewItemsListener = new ListChangeListener<S>() {
#Override
public void onChanged(ListChangeListener.Change<? extends S> c) {
getSkinnable().requestLayout();
}
};
private final WeakListChangeListener<S> weakListViewItemsListener =
new WeakListChangeListener<S>(tableViewItemsListener);
public ComboBoxTablePopupSkin(ComboBoxTablePopup comboBoxTablePopup) {
super(comboBoxTablePopup, new ComboBoxTablePopupBehavior(comboBoxTablePopup));
this.comboBoxTablePopup = comboBoxTablePopup;
setupTablePredicate();
updateComboBoxTablePopupItems();
itemsObserver = observable -> {
updateComboBoxTablePopupItems();
updateTableViewItems();
};
this.comboBoxTablePopup.itemsProperty().addListener(new WeakInvalidationListener(itemsObserver));
tableViewPopupContent = createTableView();
tableViewPopupContent.setManaged(false);
getChildren().add(tableViewPopupContent);
updateTableViewItems();
getEditor().textProperty().addListener((obv, oldValue, newValue) -> {
if (!newValue.isEmpty())
comboBoxTablePopup.show();
filtreData(newValue);
});
registerChangeListener(comboBoxTablePopup.itemsProperty(), "ITEMS");
registerChangeListener(comboBoxTablePopup.valueProperty(), "VALUE");
registerChangeListener(comboBoxTablePopup.editorProperty(), "EDITABLE");
}
private void setupTablePredicate() {
}
private void updateTableViewItems() {
filtredList = new FilteredList<S>(comboboxTablePopupItems, p -> true);
sortedList = new SortedList<S>(filtredList);
sortedList.comparatorProperty().bind(tableViewPopupContent.comparatorProperty());
tableViewPopupContent.setItems(sortedList);
}
private void filtreData(String pr) {
String data = pr;
filtredList.setPredicate(engine -> {
if (pr == null || pr.isEmpty() || pr.length() == 0)
return true;
if (((Engine) engine).getDesignation().toLowerCase().contains(pr.toLowerCase())) {
return true;
} else
return false;
});
}
public void updateComboBoxTablePopupItems() {
comboboxTablePopupItems = comboBoxTablePopup.getItems();
comboboxTablePopupItems = comboboxTablePopupItems == null ? FXCollections.<S>emptyObservableList() : comboboxTablePopupItems;
}
private TableView<S> createTableView() {
final TableView<S> tableView = new TableView<>();
tableView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
tableView.setFocusTraversable(false);
tableView.getSelectionModel().selectedItemProperty().addListener(o -> {
int index = tableView.getSelectionModel().getSelectedIndex();
System.out.println("selected item changed");
});
for (TableColumn tblColumn : tableColumns()) {
tableView.getColumns().add(tblColumn);
}
tableView.setOnKeyPressed(e -> {
if (e.getCode() == KeyCode.ENTER ||
e.getCode() == KeyCode.ESCAPE ||
e.getCode() == KeyCode.SPACE) {
S selectedItem = tableView.getSelectionModel().getSelectedItem();
if (selectedItem != null) {
System.out.println(((Engine) selectedItem).getDesignation());
getEditor().setText(((Engine) selectedItem).getDesignation());
comboBoxTablePopup.setValue(selectedItem);
comboBoxTablePopup.hide();
}
}
});
return tableView;
}
private ObservableList<TableColumn> tableColumns() {
return ((ComboBoxTablePopup) getSkinnable()).getColumns();
}
#Override
protected Node getPopupContent() {
return this.tableViewPopupContent;
}
#Override
protected TextField getEditor() {
return ((ComboBoxTablePopup) getSkinnable()).getEditor();
}
#Override
protected StringConverter getConverter() {
return ((ComboBoxTablePopup) getSkinnable()).getConverter();
}
#Override
public Node getDisplayNode() {
if (displayNode == null) {
displayNode = getEditableInputNode();
displayNode.getStylesheets().add("ComboBoxTable-display-node");
updateDisplayNode();
}
displayNode.setEditable(comboBoxTablePopup.isEditable());
return displayNode;
}
#Override
protected void handleControlPropertyChanged(String p) {
super.handleControlPropertyChanged(p);
if ("TEXT".equals(p)) {
if (!getEditor().textProperty().get().isEmpty()) {
comboBoxTablePopup.show();
}
filtreData(getEditor().textProperty().get());
} else if ("ITEMS".equals(p)) {
updateComboBoxTablePopupItems();
} else if ("EDITABLE".equals(p)) {
getEditableInputNode();
}
}
}
Use the StringConverter to convert the item to a String or use a similar property.
public class ComboBoxTablePopupSkin<S> extends ComboBoxPopupControl<S> {
...
private static final StringConverter DEFAULT_CONVERTER = new StringConverter() {
#Override
public String toString(Object o) {
return o == null ? null : o.toString();
}
#Override
public Object fromString(String s) {
throw new UnsupportedOperationException();
}
};
public final StringConverter<S> getConverter() {
StringConverter<S> converter = converterProperty().get();
// fix in case the property is set to a null
return converter == null ? DEFAULT_CONVERTER : converter;
}
private void filtreData(String pr) {
if (pr == null || pr.isEmpty()) {
filtredList.setPredicate(null);
} else {
final StringConverter<S> converter = ((ComboBoxTablePopup<S>) getSkinnable()).getConverter();
final String data = pr.toLowerCase();
filtredList.setPredicate(object -> {
String s = converter.toString(object);
return s != null && s.toLowerCase().contains(data);
});
}
}
I have created a method in which i have multiple if conditions. Now i want to refactor these if conditions. What would be the best design pattern/strategy to overcome multiple if conditions?
if
(
poConfiguration.strSampleLoaderPluginClass != null
&& poConfiguration.strSampleLoaderPluginClass.equals("") == false
)
{
setSampleLoaderPluginClass(poConfiguration.strSampleLoaderPluginClass);
}
if
(
poConfiguration.strPreprocessingPluginClass != null
&& poConfiguration.strPreprocessingPluginClass.equals("") == false
)
{
setPreprocessingPluginClass(poConfiguration.strPreprocessingPluginClass);
}
if
(
poConfiguration.strFeatureExtractionPluginClass != null
&& poConfiguration.strFeatureExtractionPluginClass.equals("") == false
)
{
setFeatureExtractionPluginClass(poConfiguration.strFeatureExtractionPluginClass);
}
if
(
poConfiguration.strClassificationPluginClass != null
&& poConfiguration.strClassificationPluginClass.equals("") == false
)
{
setClassificationPluginClass(poConfiguration.strClassificationPluginClass);
}
Please share your thoughts with implementations, if possible. Thanks in advance
My first idea would be the polymorphism (Click here for more info), it depends from the concrete situation:
interface MyInterface {
public boolean checkCondition(PoConfiguration poConfiguration);
public void process(PoConfiguration poConfiguration);
}
public class SampleLoader implements MyInterface {
public boolean checkCondition(PoConfiguration poConfiguration) {
return poConfiguration.strSampleLoaderPluginClass != null
&& !poConfiguration.strSampleLoaderPluginClass.isEmpty();
}
public void process(PoConfiguration poConfiguration) {
setSampleLoaderPluginClass(poConfiguration.strSampleLoaderPluginClass);
}
}
public class ClientAPI {
public void caller() {
for (MyInterface current : this.myInterfaces) {
if (current.checkCondition(current)) {
current.process();
}
}
}
You might try something like the following:
Create a Configuration class that contains ConfigurationItems
Each ConfigurationItem would have a name, value and a default value
As an improvement, you may want to create static values for the configuration items instead of using Strings.
TestConfig main Class
package com.example.config;
public class TestConfig {
static TestConfig me;
static String[][] confSettings = {{"sampleLoader","loaderDefault"}
,{"preProcessing","preProcessingDefualt"}
,{"featureExtraction","featureExtractionDefault"}
,{"classification","classificationDefault"}
};
// Object fields
Configuration configuration;
public static void main(String[] args) {
// TODO Auto-generated method stub
me = new TestConfig();
me.doWork();
}
private void doWork() {
configuration = new Configuration();
for (int i=0; i < confSettings.length; i++) {
configuration.addConfigurationItem(confSettings[i][0], confSettings[i][1], null);
}
configuration.setConfigurationItemDefault("classification", "newValue");
System.out.println("sampleLoader = " + configuration.getConfigurationItemValue("sampleLoader"));
System.out.println("classification = " + configuration.getConfigurationItemValue("classification"));
}
}
Configuration Class
package com.example.config;
import java.util.ArrayList;
import java.util.HashMap;
public class Configuration {
// Class fields
// Object fields
HashMap<String,Integer> itemNames;
ArrayList<ConfigurationItem> items;
public Configuration() {
items = new ArrayList<ConfigurationItem>();
itemNames = new HashMap<String,Integer>();
}
public Configuration addConfigurationItem(String name, String defaultValue, String value) {
if (itemNames.containsKey(name)) {
// handle duplicate configuration item
} else {
items.add(new ConfigurationItem(name, defaultValue, value));
Integer loc = new Integer(items.size()-1);
itemNames.put(name, loc);
}
return this;
}
public void setConfigurationItemDefault(String name, String defaultValue) {
int loc = getConfigurationItemIndex(name);
if (loc > -1) {
items.get(loc).setDefaultValue(defaultValue);
}
}
public String getConfigurationItemValue(String name) {
int loc = getConfigurationItemIndex(name);
if (loc > -1) {
return items.get(loc).getValue();
} else {
// handle unknown parameter
return null;
}
}
private int getConfigurationItemIndex(String name) {
if (itemNames.containsKey(name)) {
return itemNames.get(name);
} else {
// handle unknown parameter
return -1;
}
}
}
ConfigurationItem Class
package com.example.config;
public class ConfigurationItem {
// Object fields
String name;
String value;
String defaultValue;
public ConfigurationItem(){};
public ConfigurationItem(String name, String defaultValue, String value) {
this.setName(name).setDefaultValue(defaultValue).setValue(value);
}
public ConfigurationItem setName(String name) {
this.name = name;
return this;
}
public ConfigurationItem setValue(String value) {
this.value = value;
return this;
}
public ConfigurationItem setDefaultValue(String defaultValue) {
this.defaultValue = defaultValue;
return this;
}
public String getValue() {
if (value == null || value.length() == 0) {
return defaultValue;
} else {
return value;
}
}
}
What is the equivalent of a LinkedHashSet (Java) in C#?
HashSet does the job because it is virtually equivalent to LinkedHashSet in Java. HashSet is backed by a linked list - though the docs don't explicitly state that it preserves the order or that it is backed by a array-based linked list. You can see from the source code the implementation is a LinkedHashSet.
Duplicates are not allowed just like the Java LinkedHashSet. The one difference between this and LinkedHashSet is that if you remove something from the set, it only marks the element as free in the array, and so adding an item after a remove() fills up the empty array slots first before “appending”. The way around this is to call the TrimExcess() method. So, while it is not exactly the same in many use cases, e.g. serialize and deserialize and for effectively immutable sets once created it works great.
You can always subclass and override remove() to always call TrimExcess() to get the same behavior. And you can name the class LinkedHashSet for clarity!
using System;
using System.Collections.Generic;
namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
String[] crew = {"Spock", "Kirk", "Bones", "Picard", "Uhura", "Chekov"};
HashSet<String> linkedHashSet = new HashSet<String>(crew);
// Show order is preserved
foreach(String value in linkedHashSet){
Console.Write(value); Console.Write(" ");
}
// Remove from the middle
linkedHashSet.Remove("Picard");
Console.WriteLine();
foreach(String value in linkedHashSet){
Console.Write(value); Console.Write(" ");
}
// Add it back but it is back in the middle not the end
linkedHashSet.Add("Picard");
Console.WriteLine();
foreach(String value in linkedHashSet){
Console.Write(value); Console.Write(" ");
}
// Remove and trim then add
linkedHashSet.Remove("Picard");
linkedHashSet.TrimExcess();
linkedHashSet.Add("Picard");
Console.WriteLine();
foreach(String value in linkedHashSet){
Console.Write(value); Console.Write(" ");
}
Console.WriteLine();
}
}
}
Output:
Spock Kirk Bones Picard Uhura Chekov
Spock Kirk Bones Uhura Chekov
Spock Kirk Bones Picard Uhura Chekov
Spock Kirk Bones Uhura Chekov Picard
I completed the unfinished methods and generally polished the class that 'achitaka-san' posted.
public class LinkedHashSet<T> : ISet<T> {
private readonly IDictionary<T, LinkedListNode<T>> dict;
private readonly LinkedList<T> list;
public LinkedHashSet(int initialCapacity) {
this.dict = new Dictionary<T,LinkedListNode<T>>(initialCapacity);
this.list = new LinkedList<T>();
}
public LinkedHashSet() {
this.dict = new Dictionary<T,LinkedListNode<T>>();
this.list = new LinkedList<T>();
}
public LinkedHashSet(IEnumerable<T> e) : this() {
addEnumerable(e);
}
public LinkedHashSet(int initialCapacity, IEnumerable<T> e) : this(initialCapacity) {
addEnumerable(e);
}
private void addEnumerable(IEnumerable<T> e) {
foreach (T t in e) {
Add(t);
}
}
//
// ISet implementation
//
public bool Add(T item) {
if (this.dict.ContainsKey(item)) {
return false;
}
LinkedListNode<T> node = this.list.AddLast(item);
this.dict[item] = node;
return true;
}
public void ExceptWith(IEnumerable<T> other) {
if (other == null) {
throw new ArgumentNullException("other cannot be null");
}
foreach (T t in other) {
Remove(t);
}
}
public void IntersectWith(IEnumerable<T> other) {
if (other == null) {
throw new ArgumentNullException("other cannot be null");
}
T[] ts = new T[Count];
CopyTo(ts, 0);
foreach (T t in ts) {
if (!System.Linq.Enumerable.Contains(other, t)) {
Remove(t);
}
}
}
public bool IsProperSubsetOf(IEnumerable<T> other) {
if (other == null) {
throw new ArgumentNullException("other cannot be null");
}
int contains = 0;
int noContains = 0;
foreach (T t in other) {
if (Contains(t)) {
contains++;
} else {
noContains++;
}
}
return contains == Count && noContains > 0;
}
public bool IsProperSupersetOf(IEnumerable<T> other) {
if (other == null) {
throw new ArgumentNullException("other cannot be null");
}
int otherCount = System.Linq.Enumerable.Count(other);
if (Count <= otherCount) {
return false;
}
int contains = 0;
int noContains = 0;
foreach (T t in this) {
if (System.Linq.Enumerable.Contains(other, t)) {
contains++;
} else {
noContains++;
}
}
return contains == otherCount && noContains > 0;
}
public bool IsSubsetOf(IEnumerable<T> other) {
if (other == null) {
throw new ArgumentNullException("other cannot be null");
}
foreach (T t in this) {
if (!System.Linq.Enumerable.Contains(other, t)) {
return false;
}
}
return true;
}
public bool IsSupersetOf(IEnumerable<T> other) {
if (other == null) {
throw new ArgumentNullException("other cannot be null");
}
foreach (T t in other) {
if (!Contains(t)) {
return false;
}
}
return true;
}
public bool Overlaps(IEnumerable<T> other) {
if (other == null) {
throw new ArgumentNullException("other cannot be null");
}
foreach (T t in other) {
if (Contains(t)) {
return true;
}
}
return false;
}
public bool SetEquals(IEnumerable<T> other) {
if (other == null) {
throw new ArgumentNullException("other cannot be null");
}
int otherCount = System.Linq.Enumerable.Count(other);
if (Count != otherCount) {
return false;
}
return IsSupersetOf(other);
}
public void SymmetricExceptWith(IEnumerable<T> other) {
if (other == null) {
throw new ArgumentNullException("other cannot be null");
}
T[] ts = new T[Count];
CopyTo(ts, 0);
HashSet<T> otherList = new HashSet<T>(other);
foreach (T t in ts) {
if (otherList.Contains(t)) {
Remove(t);
otherList.Remove(t);
}
}
foreach (T t in otherList) {
Add(t);
}
}
public void UnionWith(IEnumerable<T> other) {
if (other == null) {
throw new ArgumentNullException("other cannot be null");
}
foreach (T t in other) {
Add(t);
}
}
//
// ICollection<T> implementation
//
public int Count {
get {
return this.dict.Count;
}
}
public bool IsReadOnly {
get {
return this.dict.IsReadOnly;
}
}
void ICollection<T>.Add(T item) {
Add(item);
}
public void Clear() {
this.dict.Clear();
this.list.Clear();
}
public bool Contains(T item) {
return this.dict.ContainsKey(item);
}
public void CopyTo(T[] array, int arrayIndex) {
this.list.CopyTo(array, arrayIndex);
}
public bool Remove(T item) {
LinkedListNode<T> node;
if (!this.dict.TryGetValue(item, out node)) {
return false;
}
this.dict.Remove(item);
this.list.Remove(node);
return true;
}
//
// IEnumerable<T> implementation
//
public IEnumerator<T> GetEnumerator() {
return this.list.GetEnumerator();
}
//
// IEnumerable implementation
//
IEnumerator IEnumerable.GetEnumerator() {
return this.list.GetEnumerator();
}
}
Required usings:
using System;
using System.Collections;
using System.Collections.Generic;
Warning: The class is largely untested, especially the ISet methods. Use at your own risk.
I hope someone finds this useful. :)
There is no direct equivalent in C#. The appropriate class to use depends on the desired behaviour. The HashSet class will preserve the uniqueness of the elements. You may also want to check out SortedSet and SortedDictionary.
There is no class in C# that combines a Linked List with uniqueness required in a Set data structure, so if you need both behaviours then you will need to build your own.
I have briefly implemented a HashSet which guarantees insertion order. It uses the Dictionary to look up items and the LinkedList to preserve order. All three insertion, removal and lookup work still in O(1).
public class OrderedSet<T> : ISet<T>
{
private readonly IDictionary<T, LinkedListNode<T>> m_Dictionary;
private readonly LinkedList<T> m_LinkedList;
public OrderedSet()
{
m_Dictionary = new Dictionary<T, LinkedListNode<T>>();
m_LinkedList = new LinkedList<T>();
}
public bool Add(T item)
{
if (m_Dictionary.ContainsKey(item)) return false;
var node = m_LinkedList.AddLast(item);
m_Dictionary.Add(item, node);
return true;
}
void ICollection<T>.Add(T item)
{
Add(item);
}
public void Clear()
{
m_LinkedList.Clear();
m_Dictionary.Clear();
}
public bool Remove(T item)
{
LinkedListNode<T> node;
bool found = m_Dictionary.TryGetValue(item, out node);
if (!found) return false;
m_Dictionary.Remove(item);
m_LinkedList.Remove(node);
return true;
}
public int Count
{
get { return m_Dictionary.Count; }
}
public IEnumerator<T> GetEnumerator()
{
return m_LinkedList.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public bool Contains(T item)
{
return m_Dictionary.ContainsKey(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
m_LinkedList.CopyTo(array, arrayIndex);
}
public virtual bool IsReadOnly
{
get { return m_Dictionary.IsReadOnly; }
}
public void UnionWith(IEnumerable<T> other)
{
throw GetNotSupportedDueToSimplification();
}
public void IntersectWith(IEnumerable<T> other)
{
throw GetNotSupportedDueToSimplification();
}
public void ExceptWith(IEnumerable<T> other)
{
throw GetNotSupportedDueToSimplification();
}
public bool IsSubsetOf(IEnumerable<T> other)
{
throw GetNotSupportedDueToSimplification();
}
public void SymmetricExceptWith(IEnumerable<T> other)
{
throw GetNotSupportedDueToSimplification();
}
public bool IsSupersetOf(IEnumerable<T> other)
{
throw GetNotSupportedDueToSimplification();
}
public bool IsProperSupersetOf(IEnumerable<T> other)
{
throw GetNotSupportedDueToSimplification();
}
public bool IsProperSubsetOf(IEnumerable<T> other)
{
throw GetNotSupportedDueToSimplification();
}
public bool Overlaps(IEnumerable<T> other)
{
throw GetNotSupportedDueToSimplification();
}
public bool SetEquals(IEnumerable<T> other)
{
throw GetNotSupportedDueToSimplification();
}
private static Exception GetNotSupportedDueToSimplification()
{
return new NotSupportedException("This method is not supported due to simplification of example code.");
}
}