I have this calss KeywordFilter. I want the constrcutor that accepts a keyword to create a List, add the keyword to the list and then call the constructor with the list parameter. How can I do that? because as I know, calling the constructor should be the first call.
public class KeywordFilter implements Filter {
private List<String> filteringKeywords;
public KeywordFilter(List<String> filteringKeywords) {
this.filteringKeywords = filteringKeywords;
}
public KeywordFilter(String keyword) {
List<String> filteringKeywords = new ArrayList<String>();
filteringKeywords.add(keyword);
this(filteringKeywords);//This makes a compilation error
}
}
Create your list directly :
public KeywordFilter(String keyword) {
this(new ArrayList<String>(Arrays.asList(keyword)));
}
In general, you can put the code that constructs the list in a separate function (preferably, but not necessarily, static):
private static List<String> makeFilterKeywords(String keyword) {
List<String> filteringKeywords = new ArrayList<String>();
filteringKeywords.add(keyword);
return filteringKeywords;
}
public KeywordFilter(String keyword) {
this(makeFilterKeywords(keyword));
}
This should help
public KeywordFilter(String keyword) {
this(Collections.singletonList(keyword));
}
public KeywordFilter(List<String> filteringKeywords) {
this.filteringKeywords = filteringKeywords;
}
public KeywordFilter(String keyword) {
this(((List<String>)Arrays.asList(keyword));
}
The simplest and shorten solution
public KeywordFilter(String keyword) {
this(Arrays.asList(keyword));
}
But this returns a fixed-size list backed by the specified array, without add() or remove() support.
This is applicable also to varargs
public KeywordFilter(String... keywords) {
this(Arrays.asList(keywords));
}
You can create the ArrayList with the KeyWord and then have another method append the new list to existing list (which you have created with only the keyword in the constructor).
Something like this:
public class KeywordFilter implements Filter {
private List<String> filteringKeywords;
public KeywordFilter(String keyword) { //Consctructor
filteringKeywords = new ArrayList<String>();
filteringKeywords.add(keyword);
}
public void appendList(List<String> filteringKeywords) { //new method
filteringKeywords.addAll(filteringKeywords);
}
}
Related
I have an abstract class with a single abstract method; and a number of implementing classes (about 6).
The method returns an object that "needs" two parameters.
However, in some cases, only one of the two parameters is required.
Is there an elegant way to implement this case? (instead of return this parameter as empty)
public class NormResult {
protected List<String> normWords;
protected List<String> unNormWords;
public NormResult(List<String> normWords,List<String> unNormWords) {
this.normWords = normWords;
this.unNormWords = unNormWords;
}
public NormResult(List<String> normWords) {
this.normWords = normWords;
this.unNormWords = Collections.emptyList();
}
}
public abstract class AbstractNormalizer {
protected abstract List<NormResult> doNorm();
}
public class FirstNormImpl extends AbstractNormalizer {
protected List<NormResult> doNorm() {
List<String> normWords = new ArrayList<>(5);
List<String> unNormWords = new ArrayList<>(7);
NormResult result = new NormResult(normWords, unNormWords);
return result;
}
}
public class SecondNormImpl extends AbstractNormalizer {
protected List<NormResult> doNorm() {
List<String> normWords = new ArrayList<>(8);
NormResult result = new NormResult(normWords);
return result;
}
}
if you do this to members final:
protected final List<String> normWords;
protected final List<String> unNormWords;
then in the constructor you have to initialize them both... then you can set to an empty collection or a null reference the one you dont have/need
and your overloaded constructor can look like:
public NormResult(List<String> normWords, List<String> unNormWords) {
this.normWords = normWords;
this.unNormWords = unNormWords;
}
public NormResult(List<String> normWords) {
this(normWords, Collections.emptyList());
}
The two changes I would make:
Make the fields final
Use constructor telescoping
as in:
public NormResult(List<String> normWords) {
this(normWords(), Collections.emptyList());
}
to avoid even that simple "code duplication" of assigning values twice.
Beyond that; I agree with the comments; this approach looks reasonable.
class MipRequest{
private List<String> MipIDs=null;
public List<String> getMipIDs() {
return MipIDs;
}
public void setMipIDs(List<String> mipIDs) {
MipIDs = mipIDs;
}
}
How can i call the get function?
You could call it by using object instance like:
MipRequest mipRequest = new MipRequest();
//set list...
List<String> mipIds = mipRequest.getMipIDs();
//further business logic
I want to detect when adding some items to the array list or when removing some item from it. Actually I have some code like below:
public class myClass {
MyCustomArrayList<MyObject> al;
public void method1() {
al.add(myObject);
// Do other works
al.remove(myObject)
// Do other works
}
private void DoByEachAdd() {
//I want array list call this method by adding each item to it.
// It should be in this class because it is doing some works
// related to this class. for example changing some private variables
}
private void DoByEachRemove() {
// I want array list call this method by adding each item to it.
// It should be in this class too.
}
}
I know that array list has not the ability for having listener or some kind of notifications or events and if I want to detect add should have a custom array list. something like below class:
class MyArrayList<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
}
(I get it from here)
So the question is that: how can I inform the object of MyArrayList (al) that call DoByEachAdd and DoByEachRemove methods when the remove and add method fired. Does some body have any ideas?
First, follow naming convention. Second, the three class names you used for the same class, MyList, MyArrayList and MyCustomArrayList will confuse people. As for your question, you would have to have an instance field inside MyArrayList of type myClass (unless you want to refactor DoByEachAdd and DoByEachRemove to be static). This can be done by adding it as a constructor parameter, e.g.
// inside MyArrayList
private ArrayList<T> list;
private final myClass instance;
public MyArrayList(myClass instance) { // <-- NOT MyList
list = new ArrayList();
this.myClass = myClass;
}
Also, I question your approach. Other classes with instances of MyArrayList can only use the add and remove methods of ArrayList. If you want to save a lot of bother and have all methods visible, either declare list as public final or make MyArrayList a subclass of ArrayList, e.g.
public class MyArrayList<T> extends ArrayList<T> {
private final myClass instance;
public MyArrayList(myClass instance) { // <-- NOT MyList
list = new ArrayList();
this.myClass = myClass;
}
#Override
public boolean add(T t) {
boolean returnThis = super.add(t);
// do some stuff
instance.DoByEachAdd();
return returnThis;
}
#Override
public boolean remove(T t) {
boolean returnThis = super.remove(t);
// do some stuff
instance.DoByEachRemove();
return returnThis;
}
}
If you insist on being able to return a T from remove, declare another method:
public T removeT(T t) {
remove(t);
// do some stuff
return someT;
}
you need to give access to your myClass to MyArrayList
class MyArrayList<T> {
private ArrayList<T> list;
private myClass theClass;
public MyList(myClass theClass){
list = new ArrayList<>();
this.theClass = theClass;
...
}
public void add(T t) {
list.add(t) {
//do other things you want to do when items are added
theClass.DoByEachAdd();
}
public T remove(T t) {
list.remove(t);
//do other things you want to do when items are removed
theClass.DoByEachRemove
}
and in your myClass give the object to your list
public class myClass {
MyCustomArrayList<MyObject> al;
public myClass(){
al = new MyCustomArrayList<MyObject>(this);
}
public void method1() {
al.add(myObject);
// Do other works
al.remove(myObject)
// Do other works
}
public void DoByEachAdd() {
//I want array list call this method by adding each item to it.
// It should be in this class because it is doing some works
// related to this class. for example changing some private variables
}
public void DoByEachRemove() {
// I want array list call this method by adding each item to it.
// It should be in this class too.
}
}
I've got a method called removeSup which is supposed to remove an object Supplement from a list of supplements.
this is the code for the method:
private static void removeSup(Supplement supToRemove, List<Supplement> listToRemoveFrom) {
Iterator<Supplement> iterator = listToRemoveFrom.iterator();
while(iterator.hasNext()){
if(iterator.next().equals(supToRemove)){
iterator.remove();
}
}
}
there is a class called magazine which defines the list of supplements.
public class Magazine {
private List<Supplement> supList;
public List<Supplement> getSupList() {
return this.supList;
}
public void setSupList(List<Supplement> supList) {
this.supList = supList;
}
public Magazine(Double cost, String _name){
this.supList = new ArrayList<>();
this.weekCost = cost;
this.name = _name;
}
}
the class supplement has the following constructor
public Supplement(String _name, Double _price, String _magName ){
this.name=_name;
this.price=_price;
this.magName = _magName;
}
in the main class client there is a search that the user can do to remove a certain Supplement
private static void searchSup(){
System.out.println("Search for Supplement");
String search = scanner.nextLine();
for (Supplement sup : magazine.getSupList()) {
if (!sup.getSupName().equalsIgnoreCase(search)) {
//do something
}
else{
removeSup(sup,magazine.getSupList());
}
}
}
the main method in the client class is as follows:
private Magazine magazine;
public static void main(String[] args) {
magazine = new Magazine(3.0, "pop");
List<Supplement> startList = new ArrayList<>();
startList.add(new Supplement("Nat Geo", 3.0,"pop"));
startList.add(new Supplement("Discovery", 5.0,"pop"));
startList.add(new Supplement("Health", 6.3,"pop"));
startList.add(new Supplement("IT", 8.3,"pop"));
magazine.setSupList(startList);
searchSup();
}
When I run this program and type any of the added supplements, i get an error
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
at java.util.ArrayList$Itr.next(ArrayList.java:831)
at Client.searchSup(Client.java:131)
at Client.searchSup(Client.java:140)
at Client.main(Client.java:588)
is it the for loop i am using to search giving me an error? if so how would i go about fixing this?
You generally shouldn't modify a Collection while iterating over it. It's fine to modify elements, but you really shouldn't remove something from a Collection while iterating. See here: http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html. Also, the Javadoc for ConcurrentModificationException may be helpful.
You might try returning a new list with the Supplement removed:
private static List<Supplement> removeSup(Supplement supToRemove, List<Supplement> listToRemoveFrom) {
List<Supplement> filteredSupplements = new ArrayList<Supplement>();
for(Supplement supplement : listToRemoveFrom) {
if(!suppplement.equals(supToRemove)){
filteredSupplements.add(supplement);
}
}
return filteredSupplements;
}
It seams that the "magazine" is local var in the method of main, not accessible to searchSup.Fix it like
private void searchSup(Magazine magazine)
{
//...
}
and more details if you can provide, the codes in Line 131 and 140 will be helpful.
I figured out that the search i was doing was not working with what i wanted to do so i created a method which returns an integer of the Supplement in the list.
private static int indexOfSup(List<Supplement> supSearchList, String nameOfSup) {
for (Supplement sup : supSearchList) {
if (sup.getSupName().equalsIgnoreCase(nameOfSup)) {
return supSearchList.indexOf(sup);
}
}
return -1;
}
i then use this integer to remove from the list.
a simple List.Remove(index) worked fine
Thanks for all the replies.
I have a class that i'm uses a generic Type that extends the interface zwave
everything is fine until i try to access a zwave variable for some reason the rm.keyword gives a "NullPointerException". if I cast it to the class scene it works, but that is not what I want
public <T extends zwave> T Find(List<T> Zwave,List<List<String>> listofinputstrings)
{
for(List<String> lst: listofinputstrings)
{
for(String str: lst)
{
for (T rm: Zwave)
{
//*** problem is here
//rm.keyword is always gives a NullPointerException unless i cast it to a class
if (rm.keyword.equals( str.toLowerCase()))
{
return rm;
}
}
}
}
return null;
}
//here is the interface
interface zwave
{
public String keyword="";
public String zwaveID="";
}
//here is a class that implements the interface
public class Scene implements zwave
{
String name;
String keyword;
String zwaveID;
public Scene(String Name,String Keyword,String ZwaveID)
{
name= Name;
zwaveID= ZwaveID;
keyword = Keyword;
}
}
edit
Working code
//search class
public <T extends searchable> T Find(List<T> searchableclasses, List<List<String>> listofinputstrings)
{
for(List<String> lst: listofinputstrings)
{
for(String str: lst)
{
for (T searchable: searchableclasses)
{
for(String key: searchable.GetKeywords())
{
if ( key.equals(str.toLowerCase()))
{
return searchable;
}
}
}
}
}
return null;
}
//abstract class
abstract class searchable
{
String[] keywords; //using array so i can use java's param ability
public List<String> GetKeywords()
{
return new ArrayList(Arrays.asList(keywords));
}
}
//actual class
public class Scene extends searchable
{
String name;
String zwaveID;
public Scene(String Name,String ZwaveID,String... Keywords)
{
name= Name;
zwaveID= ZwaveID;
keywords = Keywords;
}
}
If you don't wanna cast you can do some thing like this:
public <T extends zwave> T Find(List<T> Zwave,List<List<String>> listofinputstrings)
{
for(List<String> lst: listofinputstrings)
{
for(String str: lst)
{
for (T rm: Zwave)
{
if(rm instanceof Scene){
Method method=null;
try {
method = rm.getClass().getMethod("getKeyword");
if ( method.invoke(rm).equals( str.toLowerCase()))
{
return rm;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
return null;
}
NOte:define getKeyword method in Scene class:
I can customize it more with the help of java.lang.reflect. You would not even need to use instance of Scene. But I think you can do it yourself. And hope it will help.
use Reflection API to call at run time.
You need to be using a getter method. When you say rm.keyword, that's referring to a constant (zwave.keyword), which is the empty string. When you cast to Scene, the compiler sees that it's a field and looks it up instead.
Generally, you should make fields like name and keyword private unless you have a specific reason not to and use getter and setter methods to manipulate them.
The variables defined in the interface are final static public even though you didn't explicitly define. When the variable is final, once the value is assigned you cannot reassign it again.
Since you have defined as empty string ("") it will take that value. But you define the variable again in Scene class. So when you cast to Scene object will refer this variable and not the variable in the interface. Otherwise it refers to interface variable.