LinkedHashMap or two separate arrays in java - java

I have two arrays of predefined length, let us say 8, which contains related data. I can arrange them in such a way that array1[0] has corresonding mapping at array2[0]. That is key value pairs are at the same index in both arrays. In such a case, for iterating the array, I can either use a for loop like below
for(int i=0;i<array1.length;i++){
int array1Val = array1[i];
String array2Val = array2[i];
//some code
}
Is this approach gud? Or is it better to use linked hashmap instead and loop using
map.entrySet()
Complexity wise and efficiency wise which is a better approach?

Rule of thumb: When you are considering creating corresponding arrays, then it's time to create a class for that corresponding data, and create an array of that class. This is the clearest, most readable, object-oriented way to store your corresponding data in objects in Java. (It doesn't have to be called "Data".)
class Data {
private int value1;
private String value2;
// Any other arrays? Make another value here.
// Constructor, getters, setters
}
Then declare an array of that class, and store objects in it here.
Data[] mydata = new Data[length];
for (int i = 0; i < length; i++) {
mydata[i] = new Data(); // and you can then initialize the Data object too.
}
Then one for loop can access each Data object.
for (int i = 0; i < length; i++) {
Data data = mydata[i];
// Extract values here.
}
(Or you can use the enhanced "foreach" loop also.)
for (Data data : mydata) {
// Extract values here.
}

Use a map.
In terms of performance, you are iterating over the length of the data structure.
so its only o(n)
reading from a map is o(1), reading from an array is also o(1)
so really no difference in performance.
But in terms of readability and maintainability its better to have a single "map" data structure then two array data structures that need to be consumed/used in a "special way" (in this case you need to remember that array1[0] maps to array2[0]. That makes the code less readable and more complicated than it has to be.
Keep your code clean, easy to read, and simple, use a map:
Here is are ways to loop thru a map in java:
for (Map.Entry<String, Object> entry : map.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
// ...
}
for (Object value : map.values()) {
// ...
}
[UPDATE]
In response to people who suggest "hey create a Class"...
Please ask yourself "who needs to consume this data"?
If the data is only relevant to an internal method, then I suggest using an anonymous class like here:
public void myMethod(String param1, String param2) {
class MyAnonymousClass {
String data1;
String data2;
}
MyAnonymousClass anonymous = new MyAnonymousClass();
anonymous.data1 = param1;
anonymous.data2 = param2;
}
If the data is only relevant to the internals of another Class then create a private static inner class.
pubic class SomeClass {
private static class MyDataContainer {
}
}
Just be aware of these choices when creating classes.
Cheers!

Related

How to sort List<String> list numerically?

I have a List<String> list which is initialized to an arrayList. That is,
List<String>list = new ArrayList();
It has the following elements.
[1,bread, 1,turkey, 10,potato, 11,plum, 12,carrot, 2,milk, 2,rice]
I would like to sort the list so that the numbers are in ascending order. For example,
[1,bread,1 turkey,2,milk,2,rice,10,potato,11,plum,12,carrot]
How can I do that?
Java is an Object-Oriented language, and you should use it.
So, create a new class with two fields: int and String.
Now parse your strings and create objects, i.e. 1,bread is parsed into the int value 1, and the String value bread.
Next, make your class implement Comparable, and implement the compareTo method to order the objects by the int value.
Finally, now that List<String> was converted to List<MyObj>, call Collections.sort(list).
You're not trying to sort the elements in the List--you're trying to sort pairs of elements. You can't do that with a simple sort. What you'll need to do is:
Define a class with two fields, an int and a String. Make the class implement Comparable.
Define a comparator for the class that compares the int fields to get the order you want. You'll have to decide what your comparator will do if the int fields are equal (do you want the String fields to be in ascending order?)
Create a List<YourClass> whose size is half the size of the original list, by going through the source list in pairs, something like
for (int i = 0; i < list.size() - 1; i += 2) {
create a YourClass by converting list.get(i) to an int, and using list.get(i+1) as the String field
}
Sort the new list
If desired, recreate a List<String> by going through the List<YourClass> and adding a String conversion of the int, followed by the String field from YourClass, to the new list.
I don't know what you're planning to do with the String list, but in most cases it will make your program easier if you create a List<YourClass> list as soon as possible, and work with YourClass objects throughout the rest of the program
The simple answer is that you could provide a custom Comparator which understands the structure of each individual String element and can parse and compare them properly. Something like this:
#Test
public void testShouldSortByNumber() {
// Arrange
List<String> list = Arrays.asList("1,bread", "1,turkey", "10,potato", "11,plum", "12,carrot", "2,milk", "2,rice");
final List<String> EXPECTED_LIST = Arrays.asList("1,bread", "1,turkey", "2,milk", "2,rice", "10,potato", "11,plum", "12,carrot");
// Act
Collections.sort(list, new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
try {
int i1 = Integer.parseInt(o1.split(",")[0]);
int i2 = Integer.parseInt(o2.split(",")[0]);
// If the numbers are equal, could order by alpha on the second part of the string split
return i1 < i2 ? -1 : i1 == i2 ? 0 : 1;
} catch (Exception e) {
// Lots of possible errors above -- NPE, NFE, invalid string format, etc.
e.printStackTrace();
}
return 0;
}
});
// Assert
assert list.equals(EXPECTED_LIST);
}
The more complex answer is that you should better define your problem -- what should the result be if an element is empty or null, if the numbers are equal are the other strings compared lexicographically or is it irrelevant?
You may also want to use a different data structure -- if the content of each element is really two different logical concepts, a tuple or class may be correct. Or, you may want to use a SortedMap (of which TreeMap is probably the best implementation here) where the key is the "ingredient" and the value is the "count" (or "cost", I don't have any context on the numerical value).
You can also enhance the code above with a lambda if you have access to JDK 8+.

Java LinkedList obtaining first element

I have an Java LinkedList which stores two values (code below).
I was wondering how i can obtain the first value only?
I have:
LinkedList list = new LinkedList();
list.add(number+" "+string);
I want to be able to just print out number from the list. Is it possible?
First of all, note that by doing list.add(number + " " + string) you're adding a single object, namely the string formed by concatenating number and string.
That said, you could try something like this, to get the first part of the first element:
list.get(0).split(" ")[0]
Example:
int number = 17;
String string = "hello";
LinkedList<String> list = new LinkedList<String>();
list.add(number+" "+string);
// Print number of first item:
System.out.println(list.get(0).split(" ")[0]); // prints "17"
I think you mean the number only.
First get the object at index 0:
String node = list.get(0);
Then extract the first part by looking for the space
String num = node.substring(0,node.indexOf(' '));
Although I suggest looking into HashMaps for such implementation, which takes Key,Value pairs:
For your example, you will need something like:
Map<Long,String> myMap = new HashMap<Long,String>();
myMap.put(number,string);
I'd suggest encapsulating your number and string into a class, like this.
public final class Pojo {
private final Number number;
private final String string;
public Pojo(Number number, String string) {
this.string = string;
this.number = number;
}
public void getNumber() {
return number;
}
public void getString() {
return string;
}
#Override
public String toString() {
return number + " " + string;
}
}
Then, create your List like this:
List<Pojo> list = new LinkedList<Pojo>(); // use generics for compile-time type safety
list.add(new Pojo(42, "Answer to the Ultimate Question of Life, the Universe, and Everything"); // add a Pojo
System.out.println(list.get(0).getNumber());
The List does not store two values. It stores one Object, the String created by concatenating number with a space and the String.
If you want to access individual Objects, you should either use a Map instead of a List or create a custom Object that holds number and string:
a)
Map<Integer, String> map = new Hashmap<Integer, String>();
map.put(number, string);
b)
public class MyObject{
private Number number;
private String string;
// + getters and setters
}
Also:
a) you should not use Non-generic Collections anymore. Generics were introduced 7 years ago, there should not be any reason not to use them these days.
So you should use this:
LinkedList<String> list = new LinkedList<String>();
Or this:
LinkedList<MyCustomObject> list = new LinkedList<MyCustomObject>();
b) are you sure you want a LinkedList? In most cases, ArrayList is the general purpose List implementation. LinkedList performs better if you have many add() statements and don't know in advance how large your List will be, but ArrayList performs a lot better for random access.
You are adding a string to that list. x + y, where either x or y is a string produces a string. If you want to have access to the number and the string, you should consider using another type - not a String here. Something like:
LinkedList<Pair<Number, String>> list = new LinkedList<Pair<Number, String>();
list.add(new Pair<Number, String>(number, string));
This way, to obtain the number, stored in the first element of the list:
Pair thePair = list.get(0);
number = (Number)thePair.left;
Pair is a class, you can find in Apache Commons:
http://commons.apache.org/lang/api-3.0-beta/org/apache/commons/lang3/Pair.html
(A source for many useful Java classes)
number+" "+string
Acts as a single string, if you want to get the number:
list.get(index).split(" ")[0]
Even if it works, this is not a clear way to manage a pair of values.
From an object-oriented point of view (and this is the right context :D ), use directly an object:
class Pair {
int number;
String str;
}
Put your object to the list:
Pair pair = new Pair();
pair.number = 1;
pair.str = "hello";
list.add(pair);
And get your number:
((Pair)list.get(0)).number;
Of course you can use class methods and generics to manage all in a better way.
when you are initiating a Linkedlist in java, you should specify the data type that you are going to store in. You haven't done so. As your requirement it should be:
LinkedList<int> list=new LinkedList<>();
After that you can add your elements:
list.add(<number>);
Then you can get the first element:
list.getFirst();
Then you can print that.

How to convert a List of String arrays to a List of objects

I want to convert a List to a List so that each object on my new list includes the first element of each String[].
Do you know if this is possible to do in java?
for example:
public List<String[]> readFile(){
String[]array1={"A","1.3","2.4","2.3"};
String[]array2={"B","1.43","3.4","2.8"};
String[]array3={"C","5.23","2.45","2.9"};
List<String[]>ReadFile= new ArrayList<String[]>();
ReadFile.add(array1);
ReadFile.add(array2);
ReadFile.add(array3);
return ReadFile;
}
Now I want a method which will take the List ReadFile from above to somehow split the arrays of strings into an ID which will be the first element "A", "B", "C" and another part which would be the string array of numbers which I will put through another method to convert numbers from String to type Double. I have already got the method to convert to double but I need to be able to keep track of the ID field because the ID field will be used to identify the array of numbers.
A friend suggested that I create an Object where each objects has one part as a String ID and the other part as an array. That is the part which I do not know how to do.
Can anybody help please?
below is the method declaration which I believe I should have so the return type will be List where each array has been converted to an Object with two parts.
public List<Object> CreateObject(List<String[]>ReadFile){
}
Thanks,
Jetnori.
Hi all, Thank you for taking your time to help.
I can see the benefit of using HashTables. I am as of now trying to implement it. I know i might be sidetracking a little but just to explain what I am trying to do:
In my project I have CSV file with data about gene expression levels. The method that I use from OpenCSV to read the file returns a List(String[]) where each String[] is one row in the file. The first element of each row is variable name (recA, ybjE etc). The rest of the row will be numbers data related to that variable. I want to calculate Pearson's correlation between each of the number arrays. The method which I have got implemented already does that for me but the problem that I have now is that I had to remove the string values from my arrays before I could convert to double by iterating over the array. After I have managed to calculate the correlation between each array of doubles by still keeping the ID linked to the row, I want to be able to draw an undirected node graph between the genes that have a correlation higher than a threshold which I will set (for example correlation higher than 0.80). I don't know if i am biting more than i can chew but I have 30 days to do it and I believe that with the help of people like you guys I will get through it.
Sorry for going on for a bit.
thanks,
Jetnori.
I agree with the answer Alb provided, however this is what your friend has suggested, first you need a class to represent the data. I have included a constructor that parses the data and one that accepts already parsed data, depending on how you like to think of things.
public class NumberList {
private double[] numbers;
private String key;
public NumberList(Strig key, double[] numbers){
this.ley = key;
this.numbers = numbers;
}
public NumberList(String[] inputList) {
key = inputList[0];
numbers = new double[inputList.length-1];
for(int i=1;i<inputList.length;i++){
numers[i-1] = Double.parseDouble(inputList[i]);
}
}
public String getKey() {
return key;
}
public double[] getNumbers() {
return numbers;
}
}
Then you need your function to generate the list:
public List<NumberList> CreateObject(List<String[]> ReadFile){
ArrayList<NumberList> returnList = new ArrayList<NumberList>(ReadFile.size());
for (String[] input : ReadFile) {
returnList.add(new NumberList(input));
}
return returnList;
}
Note this uses the constructor that parses the data, if you use the other constructor then the "CreateObject" function would need to include the parsing logic.
Finally on a side note the standard convention in java is that the only thing that is capitalized are class names and final static fields (which appear in all caps sepearted by underscores), so conventionally the method signature would be:
public List<NumberList> createObject(List<String[]> readFile){
...
}
Sounds like you need a Map instead of a List, it lets you index things by a key (in your case ID).
Map<String, String[]> map = new Hashmap<String, String[]>();
for( String[] array : ReadFile ){
map.put( array[0], array );
}
then to get the array of values for 'A' you would do:
String[] values = map.get( "a" );
If you want the values to be doubles instead of strings you'll want to change the array before putting it (the map.put call) I'd advise using a list or other collections instead of an array also. You also will probably also want to remove the ID part from these values, which my code does not do.
public class Split_ListwithIDs {
Hashtable<String, String[]> table = new Hashtable<String, String[]>();
Splitter spl ;
public Split_ListwithIDs(Splitter split){
spl = split;
}
private void addEntry(String key , String[] vals){
table.put(key, vals);
}
public void parseList(List<String[]> list){
for(String[] entry : list){
String[] temp = new String[entry.length - 1];
System.arraycopy(entry, 1, temp, 0,entry.length - 1);
addEntry(entry[0], spl.GetStringArrayOfNumbers(temp));
}
}
class SplittingHelper implements Splitter{
#Override
public String[] GetStringArrayOfNumbers(String[] arr) {
String[] strArray = null ;
// implementation here
return arr;
}
}
interface Splitter {
String[] GetStringArrayOfNumbers(String[] arr);
}
}
You will have to use a Hashtable instead of a list of objects.( I am assuming that you will need to search through the list for a given entry using the First alphabet as key - This will be very laborious if you want to use a List ).
In the method SplittingHelper , provide your custom logic to parse the string of numbers and return another string[] of numbers.
I don't understand your goal, but for 'an object with 2 parts' you might consider storing them in a Hashtable: http://download.oracle.com/javase/6/docs/api/java/util/Hashtable.html

Java: Apply Callback to Array Values

I'm looking for a simple way to apply a callback method to each element in a String array. For instance in PHP I can make all elements in an array like this:
$array = array_map('strtolower', $array);
Is there a simple way to accomplish this in Java?
First, object arrays in Java are vastly inferior to Lists, so you should really use them instead if possible. You can create a view of a String[] as a List<String> using Arrays.asList.
Second, Java doesn't have lambda expressions or method references yet, so there's no pretty way to do this... and referencing a method by its name as a String is highly error prone and not a good idea.
That said, Guava provides some basic functional elements that will allow you to do what you want:
public static final Function<String, String> TO_LOWER =
new Function<String, String>() {
public String apply(String input) {
return input.toLowerCase();
}
};
// returns a view of the input list with each string in all lower case
public static List<String> toLower(List<String> strings) {
// transform in Guava is the functional "map" operation
return Lists.transform(strings, TO_LOWER);
}
Unlike creating a new array or List and copying the lowercase version of every String into it, this does not iterate the elements of the original List when created and requires very little memory.
With Java 8, lambda expressions and method references should finally be added to Java along with extension methods for higher-order functions like map, making this far easier (something like this):
List<String> lowerCaseStrings = strings.map(String#toLowerCase);
There's no one-liner using built-in functionality, but you can certainly match functionality by iterating over your array:
String[] arr = new String[...];
...
for(int i = 0; i < arr.length; i++){
arr[i] = arr[i].toLowerCase();
}
You could use reflection:
String[] map(java.lang.reflect.Method method, String[] array) {
String[] new_array = new String[array.length];
for (int i = 0; i < array.length; i++) new_array[i] = (String)method.invoke(null, new Object[]{array[i]});
return new_array;
}
Then you just need to declare a static method somewhere and get a reference to it using the reflection API.

List of Lists of Lists

I'm new to Java and I need to make a list of lists of lists. I could do it in python because an element of a list can be a list so in an embedded list list[0] would refer to a list and list[0][0] would refer to the zeroeth element of the embedded list. Is there any easy way to implement this behavior in java?
All the other answers are technically correct, but IMHO if you implement a rough List of Lists of Lists you are not treating your data at the right level of abstraction. For example I am pretty sure that a List of Lists already means "something" in your business domain. Encapsulate this "something" in another object so you can just have a List<Something> instead of a difficult to use and maintain List<List<List<Object>>>.
As Mario says, you probably need to abstract out your data a little further. But, the following will do what you need.
In Java you would so something like:
List<List<List<Object>>> listOfListsOfLists =new ArrayList<List<List<Object>>>();
Then to access the items, you would use:
listOfListsOfLists.get(a).get(b).get(c);
Or, to iterate over everything:
for (List<List<Object>> list2: listOfListsOfLists) {
for (List<Object> list1: list2) {
for (Object o: list1) {
// use `o`
}
}
}
Since all of these answers make me barf, can I just add the suggestion that you either
Create a data type to express your data while encapsulating the details of the structure, or at least
Create a key type that wraps an int[] (but overrides equals and hashCode properly) and use a HashMap instead? It's typically rare that your whole 3-dimensional structure will be filled up much anyway.
Even better you could encapsulate that map and use varargs for clean access.
public class NDimensionalArray<V> {
private final int dimensions;
private final Map<Key, V> values = new HashMap<Key, V>();
private NDimensionalArray(int dimensions) {
this.dimensions = dimensions;
}
public V get(int... indices) {
checkIndices(indices);
return values.get(new Key(indices));
}
public void set(V value, int... indices) {
checkIndices(indices);
values.put(new Key(indices), value);
}
private void checkIndices(int[] indices) {
if ( indices.length != dimensions ) {
throw new IllegalArgumentException();
}
}
private static final class Key {
private final int[] indices;
private Key(int[] indices) {
this.indices = indices;
}
#Override
public int hashCode() {
return Arrays.hashCode(indices);
}
#Override
public boolean equals(Object obj) {
return Arrays.equals(indices, ((Key)obj).indices);
}
}
}
If people have examples of established collections libraries that already do this sort of thing, let me know and I'll add links.
While it is certainly true that you can construct a List<List<List<whatever>>> in Java, I can't help but wonder, Why do you want to do this? Not that it's inconceivable that this is the best solution to your problem, but wow, like why?
I guess I could imagine something like
public class Employee ...
List<Employee> store; // all the employees in a store
List<List<Employee>> city; // all the store lists for a city
List<List<List<Employee>>> nation; // all the store lists for the nation
But would you really want to process it that way? I don't know, it depends on what you need to do with it.
A comprehensive example showing List-of-List with collections and generics (Java 1.5+)
// declare the list of lists
List<List<String>> listOfListOfStrings = new ArrayList<List<String>>();
// populate
List<String> listOfStrings = new ArrayList<String>(); // one inner list
listOfStrings.add("one-one");
listOfStrings.add("one-two");
listOfListOfStrings.add(listOfStrings);
listOfStrings = new ArrayList<String>(); // and another one
listOfStrings.add("two-one");
listOfStrings.add("two-two");
listOfListOfStrings.add(listOfStrings);
// access
String oneOne = listOfListOfStrings.get(0).get(0); // first element of first inner list
String twoTwo = listOfListOfStrings.get(1).get(1); // second element of second inner list

Categories

Resources