Here is my situation:
I have a method which sorts a file based on keywords and save the result into almost 21 List<String[]> variables.
List<String[]> sortKeyword(List<String[]> csvList, String[] keywords)
So call this function, I get 21 List<String[]> variables, but I don't know how to return the these lists.
After receive the return result, I also need to do for loop to update Database.
Thus I have two questions:
1. How to return the lists.
2. How to sort the return lists.
Could someone give me some advice. I really appreciate it.
Thank you
You can't return more than one object in Java but that returned object can be a collection of objects.
For your purpose you can add all those lists to a new List and return the new List.
You can return a list of lists.
List<List<String[]>> ll = new ArrayList<>();
ll.add(list1);
ll.add(list2);
return ll;
To return the three lists, either you create a wrapper class to add all the three lists to it or simply create a list of lists.
Another problem in your code, :
Use equals for string comparisoon:
if(kWord =="kWord1")
should be replaced to
if(kWord.equals("kWord1"))
Change the return type from List<String[]> to Map<String, ArrayList<String[]>>. The map String key will store the keyword and the ArrayList value will store the result line.
If I understand your problem, you're doing the above in a function and want to get the function to return all three lists, list1, list2, and list3.
In this case, you could return an array of three lists, or an ArrayList of three lists. In general, if I want a function that returns multiple values (that may not all be the same type), I usually just create a small class to contain them:
private static class KeywordSearchResults {
List<String[]> list1;
List<String[]> list2;
List<String[]> list3;
KeywordResults (List<String[]> list1, List<String[]> list2,
List<String[]> list3) {
this.list1 = list1; this.list2 = list2; this.list3 = list3;
}
}
(I usually do this as a nested class; whether to make it private or public depends on your needs.)
Normally it's a bad idea to declare a class with non-private fields, but I think if you're just using it as a wrapper just to return multiple values from a function or to create an object whose only purpose is to pass certain fields around together, and there aren't any other methods in the class, I think it's fine because the class doesn't really represent some "higher concept". Still, this is the kind of solution you'd adopt only when it's really appropriate; I think it's best to look around to see if there's a better design.
Related
Hello I would like to make a custom method for ArrayList class.
So lets say I make a new ArrayList.
ArrayList<String> list = new ArrayList<String>
I would like to make a method I can call on list.
Something like this:
list.myMethod();
What I want to solve with my method is so you can get an Object by Object name and not index inside the ArrayList.
So basically I want to make a method returning following:
list.get(list.indexOf(str));
To sum it up:
ArrayList<String> list= new ArrayList<>();
String str = "asd";
String str2 = "zxc";
list.add(str2);
list.add(str);
System.out.println(list.get(0));
System.out.println(list.get(list.indexOf(str)));
Will print: "asd" "asd".
So instead of writing: list.get(list.indexOf(Object))
I would like to be a able to write list.myMethod(Object) and get the same result. I hope you understand my question. I know this is probably a dumb solution and I could just use a Map. But this is for learning purpose only and nothing I will use.
Custom method >>
public class MyArrayList<E> extends ArrayList<E> {
public E getLastItem(){
return get(size()-1);
}
}
How to use it >>
MyArrayList<String> list= new MyArrayList<>();
String str = "asd";
String str2 = "zxc";
list.add(str2);
list.add(str);
System.out.println(list.getLastItem());
what you need requires to extend the ArrayList classs, but you should consider using instead a
Map<String, Object>
with that approach you can do something like
myMap.get("myObject1");
You should just extend the ArrayList class creating your own with the new method. But the performance would be horrible if your list grow too much. The indexOf method have O(n), so greater is the size of your array longer is the time you have to wait.
May be you should choose a different collection if you want access directly to the element. In your case, it elements stored in the collection are unique, you could use a Set.
On the other hand, a Set does not preserve the insertion order. I don't know if this is a think you have to care of.
And a Set just let you know if the element is contained into the collection.
Another collection that can be of your interest is the Map, this is a key-value collection.
But given that you have only keys this it seems not be your case.
Suppose I have two Lists and I want to copy/assign all of one list to another list with preserving reference to the original list. I use this code
List<String> mylist = new List<String>();
List<String> another = getSomeList();
// I have to do
mylist.clear();
mylist.addAll(another);
This works fine, but my question is, is there any better way to do this?
Thanks
I don't think that there is an easier way. You can just implement your own list that has e.g. a setAll() method.
class MyArrayList<E> extends ArrayList<E> {
public void setAll(Collection<E> collection) {
clear();
addAll(collection);
}
}
But this only moves the the clear() and addAll() invokation into another method. Sure from a clients prespective it makes the call easier
MyArrayList<String> mylist = new MyArrayList<String>();
mylist.setAll(another);
but at the price that you use a special list implementation. Maybe you only use this implementation inside of a class and your api does not expose that you use a MyArrayList. Than it might be ok. I would just do it the way you already do.
is there any better way to do this?
No, not for your specifications. You can delete mylist = another;.
And there's no need to call mylist.clear() when you just assigned mylist = new List<String>();
So really all you need is that last line where you addAll(another).
You can loop through first and add all elements into another:
for(String s : mylist){
another.add(s);
}
Lets say I have an array of an array of strings:
ArrayList<ArrayList<String>> arrayOfArray= new ArrayList<ArrayList<String>>();
Maybe it could look something like this(eg.):
arrayOfArray = [[A,1,B,2],[C,1,D,2],[C,1,D,2],[A,1,B,2]]
In the end I want this(duplicates was removed):
arrayOfArrayNoDuplicates = [[C,1,D,2],[A,1,B,2]]
Then as a final step I want this array of array to be sorted on the first item in the array.
Looks like this array of array maybe was sorted on the A or the B.
arrayOfArraySorted = [[A,1,B,2],[C,1,D,2]]
Is this possible without also sorting the inner array? I want to keep the order within the array "A,1,B,2".
I hope you understand want I want to do:)
/M
You use a set
It functions like an array, it dedupes
You can use a Set with a Comparator fot that.
Set<List<String>> list = new TreeSet<ArrayList<String>>(
new Comparator<List<String>>() {
public int compare(List<String> left, List<String> right) {
//check here if equal, before or after...
}
}
);
You should really use a HashSet or similar to remove duplicates from your collection of data (sets can only contain unique elements). I'm unsure how effective this will be against ArrayList's of varying contents though, so you might be best off extending ArrayList<String> and implementing your own bool equals(Object a) method (for your inner arrays).
To then sort your collection you should using Collections.sort(), you can then pass this a custom Comparator to sort them by whichever order you please. (A comparator lets you provide a method that takes 2 objects and rates their order.) Or if you've extended ArrayList<String> simply add the compare method to your class and add implements Comparator.
An example Comparator would be;
import java.util.*;
class ALComparator implements Comparator<ArrayList<String>>
{
#Override
public int compare(ArrayList<String> a, ArrayList<String> b)
{
if(a.size()==b.size())
return 1;
if(a.size()==0)
return -1;
if(b.size()==0)
return 1;
return a.get(0).compareTo(b.get(0));
}
}
This is a simple question but if I do
List<Object> list = getObjectsFromDatabase();
This would not be the correct way to handle this?
But this would?
List<Object> firstList = getObjectsFromDatabase();
List<Object> list = new ArrayList<Object>(firstList);
Or if I had a class
public class ReportDisplayModel<T> {
public ReportDisplayModel(List<T> data) {
this.data = data;
}
public List<T> data;
}
And I wanted to set the data in this model I would use the constructor?
ReportDisplayModel<Object> model = new ReportDisplayModel<Object>(getData());
Instead of
ReportDisplayModel<Object> model = new ReportDisplayModel<Object>();
model.data = getData();
Just need a clarification. Thanks.
It depends entirely on what getData() returns.
usually it is made to return Collections.unmodifiableList(result) so that clients can't modify the result.
if this result is not used anywhere else, and modifications to it doesn't mess with anything, it is fine to use the result as-is
It is rarely needed to use the copy constructor - use it when you are sure that modifying the data will impact some other component.
Regarding
List<Object> list = getObjectsFromDatabase();
vs
List<Object> firstList = getObjectsFromDatabase();
List<Object> list = new ArrayList<Object>(firstList);
either approach is fine. Depends on if you want list to refer to the list returned by getObjectsFromDatabase() or if you want it to refer to a copy of it.
If simply want to, say, print the database objects, the first approach is fine.
If you want to, say, filter out half of the database objects (i.e., remove objects from the list), and you can't say for sure that getObjectsFromDatabase() returns a mutable list, then you'll have to go with the second approach.
Regarding
ReportDisplayModel<Object> model = new ReportDisplayModel<Object>(getData());
vs
ReportDisplayModel<Object> model = new ReportDisplayModel<Object>();
model.data = getData();
I'd prefer the first method. Simply because I wouldn't want to worry about null pointer exceptions etc if I accidentally do something like
ReportDisplayModel<Object> model = new ReportDisplayModel<Object>();
model.printData();
model.data = getData();
I don't quite get your question, but I'll give it a try.
The main difference is that using the copy constructor creates a new independent copy of the list, i.e.
List<Object> firstList = getObjectsFromDatabase(); // firstList is the list returned by the database
List<Object> list = new ArrayList<Object>(firstList); //list is an independent copy of firstList
Now if you change firstList the list returned by getObjectsFromDatabase() would be changed as well (or would throw an exception if changes are not supported). On the other hand list could freely be changed without the original list being affected.
Avoid using the equal sign, because it breaks encapsulation (bad practice). Go for the copy constructor (best practice).
I have a hashMap. Each "Value"is going to be a a list which will be mapped later on with my "Key"s. List is desired to look like this:
[length,time][length,time][length,time]
For example:
Key{srcAddr=x, dstAddr=y, srcPort=12345, dstPort=80}
value{(6523,0.001),(124,0.05), () , (), ...}
I just wonder how can I have a two-col arrayList.
package myclassifier;
import java.util.ArrayList;
public class FlowStatics {
int packetLength;
double timeArrival;
public FlowStatics(int pLength, double tArrival)
{
this.packetLength = pLength;
this.timeArrival = tArrival;
}
}
and here is how I used it:
final ArrayList<FlowStatics> staticsArray = new ArrayList<FlowStatics>();
final HashMap<Flows, ArrayList> myHashMap = new HashMap<Flows, ArrayList>();
FlowStatics flowStatics = new FlowStatics(packetLength,timeArrival);
staticsArray.add(flowStatics);
myHashMap.put(flows, staticsArray);
and here is the part that I am reading it:
Iterator<Flows> iterator = myHashMap.keySet().iterator();
while(iterator.hasNext()){
Flows key = iterator.next();
ArrayList value = myHashMap.get(key);
System.out.println("Fows"+key+"----------"+"Statics"+ value);
Well, your FlowStatics is the correct solution
List<FlowStatics> will give you the "two-column array list".
Update: as of your update, myHashMap.put(flows, flowStatics); is wrong. You are this putting an individual pair, rather than a list in the map. You should use:
staticsArray.add(flowStatics);
myHashMap.put(flows, staticsArray);
A List<E> is an abstraction for a homogeneous list of elements whose type is E. There are some restrictions (e.g. no primitives), but conceptually the type E can be defined to be whatever you want.
Suppose there's an abstraction of Pair<L,R>. Then a List<Pair<L,R>> is still a list of some E, but now that E is a Pair<L,R>. So it's still a "one-column" list, but each element in the list is a "pair", so it's sort of a "two-column" list.
Note that you don't always need a generic Pair<L,R>. Any type E that properly encapsulates all the information can be used in a List<E>.
And by the way, you can have a List<List<E>> too.
See also
Wikipedia/Encapsulation
Related questions
What is the equivalent of the C++ Pair<L,R> in Java?
List of Lists of Lists
Returning values analogy
Often people ask "How can I return two values in Java?". The answer is analogous. You return one value, a new type which encapsulates both information.
So instead of:
// attempt to return two values
// DOES NOT COMPILE
return "James Bond";
return "007";
You do:
return new SecretAgent("James Bond", "007");
Related questions
Using a java method to return multiple values?