Converting traditional nested if else condition to java 8 optionals efficiently - java

Object ab = someMethod1()
if(ab != null) {
someMethod2(ab);
} else {
someMethod3()
}
converted to java optionals
Optional.ofNullable(someMethod1()).map( e -> someMethod2(ab))
.orElseGet(() -> someMethod3() );
but for the can you please help me out out to convert
// Multiple nested if else conditions are there , finding difficulty to convert to java 8 optionals
public void a() {
Object ab = someMethod1();
if(ab != null) {
Object cd = someMethod2();
if(cd != null) {
Object ef = someMethod3();
if( ef!= null) {
someMethod4();
} else {
elseMethod3()
}
} else {
elseMethod2()
}
} else {
elseMethod1();
}
}

public class a {
static String method1(String agr) {
return "method1";
}
static String method2(String agr) {
return "method2";
}
static String method3(String agr) {
return "method3";
}
public static Optional<String> cal(Optional<String> optionalS, Function<String, String> function, String agr) {
if (optionalS.isPresent())
return Optional.of(function.apply(agr));
return Optional.empty();
}
public static void main(String agr[]) {
cal(Optional.empty(), a::method1, "agr func1").orElseGet(() ->
cal(Optional.empty(), a::method2, "agr func2").orElseGet(() ->
cal(Optional.ofNullable("c"), a::method3, "agr func3").orElse("final result")
)
);
}
}

Related

How to avoid this multiple if else condition in java

My code looks like
public void convertValues(String sourceValue,String targetValue) {
if (sourceValue.equals(targetValue)) {
//dosomething
} else if (sourceValue.equals(value1) && targetValue.equals(value2)) {
//dosomething
} else if (sourceValue.equals(value2) && targetValue.equals(value1)) {
//dosomething
}
}
like that I have some 40 condition, I know writing those if else condition is stupidity.
Is it good approach to use enums or hashmaps?
To speedup entering a spaghetti code, you probably need to prepare a helper class that would simplify adding the repeated lines.
If you don't like using else if, use return; (Caution: snobbish people are allergic to seeing return not at the end).
Use a helper class / method for checking values.
Example:
public class Main {
String value1 = "a";
String value2 = "b";
String value3 = "c";
String value4 = "d";
// use a nested private class where you could add all long
// and repetitive methods that need to be done
// with source and target
private class Helper {
private String src;
private String tgt;
Helper(String src, String tgt) {
this.src = src;
this.tgt = tgt;
}
public boolean eq(String val, String val1) {
return src.equals(val) && tgt.equals(val1);
}
// add other repetitive functions here
}
public void convertValues(String sourceValue, String targetValue) {
// use a simple name for the helper class.
Helper $ = new Helper(sourceValue, targetValue);
if (sourceValue.equals(targetValue)) {
// put your execution lines into a separate method.
// this way, it will become reusable and much easier to maintain
// call a method1
return;
}
if ($.eq(value1, value2)) {
// call a method2
return;
}
if ($.eq(value2, value1)) {
// call a method3
return;
}
if ($.eq(value1, value3)) {
// call a method4
return;
}
// ....
}
// public void method1()
// public void method2()
public static void main(String[] args) throws java.lang.Exception {
// Everything else
}
}
Using lambda expressions in Java 8, it can be implemented like:
Define Value class:
public class Value {
private final String value1;
private final String value2;
// Function to exetute
private final BiConsumer<String, String> f;
public Value(String value1, String value2, BiConsumer<String, String> f) {
super();
this.value1 = value1;
this.value2 = value2;
this.f = f;
}
public boolean execute(String src, String tgt) {
if(src.equals(value1) && tgt.equals(value2)) {
f.accept(src, tgt);
return true;
}
return false;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((value1 == null) ? 0 : value1.hashCode());
result = prime * result + ((value2 == null) ? 0 : value2.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Value other = (Value) obj;
if (value1 == null) {
if (other.value1 != null)
return false;
} else if (!value1.equals(other.value1))
return false;
if (value2 == null) {
if (other.value2 != null)
return false;
} else if (!value2.equals(other.value2))
return false;
return true;
}
}
// Initialize values
Set<Value> values = new HashSet<>();
values.add(new Value("value1", "value2", (src, tgt) -> {/* do something here */}));
values.add(new Value("value2", "value1", (src, tgt) -> {/* do something here */}));
values.add(new Value("value4", "value5", (src, tgt) -> {/* do something here */}));
// Execute
if (sourceValue.equals(targetValue)) {
//dosomething
} else {
for(Value v:values) {
if(v.execute(src, tgt)) {
break;
}
}
}

Make Custom Control Generic

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);
});
}
}

Parse custom Objects with string input

I want to parse objects where I have an input value. The object has subclasses.
I don't want to create an instance when I want to parse the string.
But I want to override the method 'parse'.
class A {
public A(object param) {
//code
}
public A parse(String input) {
//code
}
}
class B extends A {
public B parse(String input) {
//code
}
}
And when I parse the objects I want do it with reflection:
A newObject = Class.forName(className).getMethod("parse", myParseText);
Is there a nice way to do that.
For maximum flexibility I'd move the parsing code out into a separate parser class. The following code is for example a simplified implementation of a parser class I am using in a project myself:
public final class ParseUtil {
public interface IStringParser<E> {
public E parse(String s) throws ParseException;
}
private ParseUtil() {}
private static Map<Class<?>, IStringParser<?>> STRING_PARSERS = new ConcurrentHashMap<>();
public static <E> void registerStringParser(Class<E> c, IStringParser<E> p){
STRING_PARSERS.put(c, p);
}
#SuppressWarnings("unchecked")
public static <E> IStringParser<E> getStringParser(Class<E> c){
return (IStringParser<E>) STRING_PARSERS.get(c);
}
public static <E> E parse(String s, Class<E> clazz) throws ParseException{
if (s == null || s.length() == 0 || clazz == null) {
throw new IllegalArgumentException();
}
IStringParser<E> stringParser = getStringParser(clazz);
if (stringParser == null) {
throw new ParseException(clazz);
}
return stringParser.parse(s);
}
}
One can then register IStringParser implementations for arbitrary classes to the ParserUtil like so:
ParseUtil.registerStringParser(File.class, new IStringParser<File>() {
#Override
public File parse(String s)throws ParseException {
return new File(s);
}
});
Or using a lambda: ParseUtil.registerStringParser(File.class, s -> new File(s));
It is the responsibility of the caller to decide how to parse a class and when the IStringParser is registered/unregistered.
By moving the parsing code away from the class itself, it is easy to change the implementation later simply by registering a different IStringParser or by changing the parse method of the ParseUtil class. For example in my own project I use the following parse method that provides some reasonable defaults for well known Java classes and uses Gson to parse Objects for which no other IStringParser is registered:
public static <E> E parse(String s, Class<E> clazz) throws ParseException{
if (s == null || s.length() == 0 || clazz == null) {
throw new IllegalArgumentException();
}
IStringParser<E> stringParser = getStringParser(clazz);
if (stringParser != null) {
return stringParser.parse(s);
}
if (Number.class.isAssignableFrom(clazz)) {
// simple number
try {
if (clazz == Integer.class) {
return clazz.cast(Integer.parseInt(s));
}
if (clazz == Long.class) {
return clazz.cast(Long.parseLong(s));
}
if (clazz == Double.class) {
return clazz.cast(Double.parseDouble(s));
}
if (clazz == Float.class) {
return clazz.cast(Float.parseFloat(s));
}
if (clazz == Short.class) {
return clazz.cast(Short.parseShort(s));
}
if (clazz == Byte.class) {
return clazz.cast(Byte.parseByte(s));
}
} catch (NumberFormatException e) {
throw new ParseException(clazz, e);
}
}
if (clazz == String.class) {
return clazz.cast(s);
}
if (clazz == Character.class) {
if (s.length() == 1) {
return clazz.cast(s.charAt(0));
} else{
throw new ParseException("Unable to parse Character \"" + s + "\"");
}
}
if (clazz == Boolean.class) {
switch (s) {
case "true":
return clazz.cast(Boolean.TRUE);
case "false":
return clazz.cast(Boolean.FALSE);
case "1":
return clazz.cast(Boolean.TRUE);
case "0":
return clazz.cast(Boolean.FALSE);
default:
throw new ParseException("Unable to parse boolean \"" + s + "\"");
}
}
if (clazz == Class.class) {
try {
return clazz.cast(Class.forName(s));
} catch (ClassNotFoundException e) {
throw new ParseException(clazz, e);
}
}
if (Enum.class.isAssignableFrom(clazz)) {
#SuppressWarnings({ "rawtypes" })
Class c = (Class)clazz;
#SuppressWarnings("unchecked")
Object o = Enum.valueOf(c, s);
return clazz.cast(o);
}
E result = null;
try {
// if all else fails use Gson to parse the class
result = getGSON().fromJson(s, clazz);
} catch (JsonSyntaxException e) {
throw new ParseException(clazz. e);
}
if (result == null) {
throw new ParseException(clazz);
}
return result;
}

Refactoring multiple if conditions

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;
}
}
}

Java implementing comparator on ArrayList

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));
}

Categories

Resources