Java Android Arraylist string to ArrayList custom class - java

How can I convert values here:
List<String> values = new ArrayList<String>
to :
ArrayList<Custom>
EDIT:
public class Custom {
public Custom Parse(String input) {
// What should I do here?
}
}

You could use:
List<Custom> customList = new ArrayList<Custom>();
for (String value: values) {
customList.add(new Custom(value));
}
Although it would be better just to add a constructor with a String argument:
class Custom {
private final String input;
public Custom(String input) {
this.input = input;
}
// not needed but implemented for completeness
public static Custom parse(String input) {
return new Custom(input);
}
}

Assuming your list of Custom objects has the same size with values list.
With one enhanced for-loop, set the appropriate fields of your objects like this:
int i=0;
for(String str:values)
customList.get(i++).setSomeProperty(str);

you can find a solution using Google Collections libraries on this thread Converting a List<String> to a List<Integer> (or any class that extends Number)

Related

Add values from basic array to Set<String>

private Set<String> fields = new HashSet<>();
public void fields(String... s){
this.fields.addAll(s);
}
Doesn't compile, saying that:
addAll
(java.util.Collection<? extends java.lang.String>)
in Set cannot be applied
to
(java.lang.String[])
is there is a good way to get around this?
I think you can convert your array to a list first. Maybe something like
this.fields.addAll(Arrays.asList(s));
If you further don't want to modify the Set, you can use Set.of with Java-9+ as:
public void fields(String... s) {
this.fields = Set.of(s);
}
or else you can use Collections.addAll as in:
public void fields(String... s) {
Collections.addAll(fields, s);
}
You simply convert array to Set as below code.
String [] array = new String[] {"one","two","three","four","five"};
Set<String> set = new HashSet<String>(Arrays.asList(array));
If you can use google Guava the follow code may help you
public void fields(String... s) {
this.fields.addAll(Sets.newHashSet(s));
}
another method:
public void fields1(String... s) {
Sets.union(fields,Sets.newHashSet(s)).copyInto(fields);
}

Cross between an Enum and a Dictionary

In my Java project, I have a need to work with a handful of strings (about 10-30 at a time). I want a data structure to hold them, with properties like so:
Can assign a unique name to each string
The unique names can be used in the code just as if they were variables, with support for IDE auto-complete, no calling getValue() or toString(), etc.
Can iterate over each value in the data structure
In practice, I'd want the code to look something like this:
MagicalDataStructure<String> mds = new MagicalDataStructure(
FirstString = "foo",
SecondString = "bar",
);
/*
This section would output:
foo
bar
*/
for (String value : mds) {
System.out.println(value);
}
/*
This section would output:
The first value is: foo
*/
System.out.println("The first value is: " + FirstString);
Things I've considered:
A class full of static finals. This satisfies #1 and #2, but I can't iterate over them -- at least not without resorting to dark-mojo reflection.
A dictionary. This satisfies #1 and #3, but the keys wouldn't be auto-completable, and there's additional syntax involved in accessing the values.
An enum. This also solves #1 and #3, but accessing the string value takes a little bit of extra code.
Is there a data structure, library, etc that will do what I want?
I would definitely favor a Map for this:
public enum PagePath {
PATH1,
PATH2,
// etc.
}
public static final Map<PagePath, String> ALL_PATHS;
static {
Map<PagePath, String> paths = new EnumMap<>(PagePath.class);
paths.put(PagePath.PATH1, "/html/div[0]/h1");
paths.put(PagePath.PATH2, "/html//form/input[id='firstname']");
// etc.
// Make sure no one breaks things by removing entries
// or by adding enum constants while forgetting to account
// for them in the above Map.
if (!paths.keySet().equals(EnumSet.allOf(PagePath.class))) {
throw new RuntimeException(
"Map does not have entries for all PagePath constants!");
}
ALL_PATHS = Collections.unmodifiableMap(paths);
}
Another possibility, as you’ve mentioned, is using String constants. You can place the initialization of those constants inside the initialization of the “all values” list, to make sure none of them are forgotten:
public static final String PATH1;
public static final String PATH2;
// etc.
public static final Collection<String> ALL_PATHS;
static {
ALL_PATHS = Collections.unmodifiableCollection(Arrays.asList(
PATH1 = "/html/div[0]/h1",
PATH2 = "/html//form/input[id='firstname']",
// etc.
));
}
If someone removes a constant, they’ll be forced to remove its initialization from the Arrays.asList call. If someone adds a constant, and keeps it consistent with the other constants’ declarations, they will be forced to add it to the ALL_PATHS List, since failing to do so would mean it never gets initialized, which compiler will catch.
If your strings are properties your may want to use RessourceBundle or Properties. This can be use to solve problem 1/3.
To solve problem 2, you may create Enum that are Keys to your HashMap so that you need to write hashMap.get(enum) that will auto-complete everything. This solution add words but benefit from auto-completion.
Can you just write a custom method to return the string values using enum?
public enum MagicalDataStructure {
FirstString("foo"),
SecondString("bar");
String value;
MagicalDataStructure(String value) {
this.value = value;
}
public static List<String> getMagicalStrings() {
List<String> strings = new ArrayList<String>();
for (MagicalDataStructure item : MagicalDataStructure.values()) {
strings.add(item.value);
}
return strings;
}
}
And call the function wherever you need to iterate:
public static void main(String[] args) {
for (String magicalString: MagicalDataStructure.getMagicalStrings()) {
System.out.println(magicalString);
}
}
How about this :) The main idea here is the following we use the EnumMap as a base for our CustomEnumMap. My understanding is that you don't need put methods so our first task is to actually throw Unsupported Operation for them. The second step is to define the different enums with the values they are actually representing. The third step is achieved through a static method that converts any Enumeration into our CustomEnumMap. How the map is later used you can see for yourself.
There is one place for improvement though and it is the implementation of the static method. Unfortunately I am just learning java 8 lambdas so I was not able to implement it fast in a good way. But I will work on that and will give you the final implementation of this method later. Or is someone wants to help me out with it is welcome.
public static class CustomEnumMap<K extends Enum<K>,V> extends EnumMap<K, V> {
public CustomEnumMap(EnumMap<K, ? extends V> m) {
super(m);
}
#Override
public V put(K key, V value) {
throw new UnsupportedOperationException();
}
#Override
public void putAll(Map<? extends K, ? extends V> m) {
throw new UnsupportedOperationException();
}
}
public static enum EnumA {
FIRST("value1"),SECOND("value2"),THREE("value3");
private String value;
private EnumA(String value) {
this.value = value;
}
public String toString() {
return value;
}
}
public static enum EnumB {
FIRST("value1"),SECOND("value2");
private String value;
private EnumB(String value) {
this.value = value;
}
public String toString() {
return value;
}
}
public static <T extends Enum<T>> CustomEnumMap<T, String> toMap(T[] myenum) {
return new CustomEnumMap<T,String>(new EnumMap<T,String>( Arrays.stream(myenum).collect(Collectors.toMap(t->(T)t, t->t.toString()))));
}
public static void main(String args[]) {
CustomEnumMap<EnumA, String> enumA = toMap(EnumA.values());
CustomEnumMap<EnumA, String> enumB = toMap(EnumA.values());
for (String stringA : enumA.values()) {
System.out.print(stringA);
}
System.out.println("");
for (String stringB : enumB.values()) {
System.out.print(stringB);
}
}

Create an ArrayList with multiple object types?

How do I create an ArrayList with integer and string input types? If I create one as:
List<Integer> sections = new ArrayList <Integer>();
that will be an Integer type ArrayList.
If I create one as:
List<String> sections = new ArrayList <String>();
that will be of String type.
How can I create an ArrayList which can take both integer and string input types?
Thank you.
You can make it like :
List<Object> sections = new ArrayList <Object>();
(Recommended) Another possible solution would be to make a custom model class with two parameters one Integer and other String. Then using an ArrayList of that object.
(1)
ArrayList<Object> list = new ArrayList <>();`
list.add("ddd");
list.add(2);
list.add(11122.33);
System.out.println(list);
(2)
ArrayList arraylist = new ArrayList();
arraylist.add(5);
arraylist.add("saman");
arraylist.add(4.3);
System.out.println(arraylist);
You can use Object for storing any type of value for e.g. int, float, String, class objects, or any other java objects, since it is the root of all the class. For e.g.
Declaring a class
class Person {
public int personId;
public String personName;
public int getPersonId() {
return personId;
}
public void setPersonId(int personId) {
this.personId = personId;
}
public String getPersonName() {
return personName;
}
public void setPersonName(String personName) {
this.personName = personName;
}}
main function code, which creates the new person object, int, float, and string type, and then is added to the List, and iterated using for loop. Each object is identified, and then the value is printed.
Person p = new Person();
p.setPersonId(1);
p.setPersonName("Tom");
List<Object> lstObject = new ArrayList<Object>();
lstObject.add(1232);
lstObject.add("String");
lstObject.add(122.212f);
lstObject.add(p);
for (Object obj : lstObject) {
if (obj.getClass() == String.class) {
System.out.println("I found a string :- " + obj);
}
if (obj.getClass() == Integer.class) {
System.out.println("I found an int :- " + obj);
}
if (obj.getClass() == Float.class) {
System.out.println("I found a float :- " + obj);
}
if (obj.getClass() == Person.class) {
Person person = (Person) obj;
System.out.println("I found a person object");
System.out.println("Person Id :- " + person.getPersonId());
System.out.println("Person Name :- " + person.getPersonName());
}
}
You can find more information on the object class on this link Object in java
List<Object> list = new ArrayList<>();
list.add(1);
list.add("1");
As the return type of ArrayList is object, you can add any type of data to ArrayList but it is not a good practice to use ArrayList because there is unnecessary boxing and unboxing.
You could create a List<Object>, but you really don't want to do this. Mixed lists that abstract to Object are not very useful and are a potential source of bugs. In fact the fact that your code requires such a construct gives your code a bad code smell and suggests that its design may be off. Consider redesigning your program so you aren't forced to collect oranges with orangutans.
Instead -- do what G V recommends and I was about to recommend, create a custom class that holds both int and String and create an ArrayList of it. 1+ to his answer!
Create your own class which stores the string and integer, and then make a list of these objects.
class Stuff {
private String label;
private Integer value;
// Constructor
public void Stuff(String label, Integer value) {
if (label == null || value == null) {
throw NullPointerException();
}
this.label = label;
this.value = value;
}
// getters
public String getLabel() {
return this.label;
}
public Integer getValue() {
return this.value;
}
}
Then in your code:
private List<Stuff> items = new ArrayList<Stuff>();
items.add(new Stuff(label, value));
for (Stuff item: items) {
doSomething(item.getLabel()); // returns String
doSomething(item.getValue()); // returns Integer
}
It depends on the use case. Can you, please, describe it more?
If you want to be able to add both at one time, than you can do the which is nicely described by #Sanket Parikh. Put Integer and String into a new class and use that.
If you want to add the list either a String or an int, but only one of these at a time, then sure it is the List<Object>
which looks good but only for first sight! This is not a good pattern. You'll have to check what type of object you have each time you get an object from your list. Also This type of list can contain any other types as well.. So no, not a nice solution. Although maybe for a beginner it can be used. If you choose this, i would recommend to check what is "instanceof" in Java.
I would strongly advise to reconsider your needs and think about maybe your real nead is to encapsulate Integers to a List<Integer> and Strings to a separate List<String>
Can i tell you a metaphor for what you want to do now? I would say you want to make a List wich can contain coffee beans and coffee shops. These to type of objects are totally different! Why are these put onto the same shelf? :)
Or do you have maybe data which can be a word or a number? Yepp! This would make sense, both of them is data! Then try to use one object for that which contains the data as String and if needed, can be translated to integer value.
public class MyDataObj {
String info;
boolean isNumeric;
public MyDataObj(String info){
setInfo(info);
}
public MyDataObj(Integer info){
setInfo(info);
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
this.isNumeric = false;
}
public void setInfo(Integer info) {
this.info = Integer.toString(info);
this.isNumeric = true;
}
public boolean isNumeric() {
return isNumeric;
}
}
This way you can use List<MyDataObj> for your needs. Again, this depends on your needs! :)
Some edition: What about using inharitance? This is better then then List<Object> solution, because you can not have other types in the list then Strings or Integers:
Interface:
public interface IMyDataObj {
public String getInfo();
}
For String:
public class MyStringDataObj implements IMyDataObj {
final String info;
public MyStringDataObj(String info){
this.info = info;
}
#Override
public String getInfo() {
return info;
}
}
For Integer:
public class MyIntegerDataObj implements IMyDataObj {
final Integer info;
public MyIntegerDataObj(Integer info) {
this.info = info;
}
#Override
public String getInfo() {
return Integer.toString(info);
}
}
Finally the list will be: List<IMyDataObj>
You don't know the type is Integer or String then you no need Generic. Go With old style.
List list= new ArrayList ();
list.add(1);
list.add("myname");
for(Object o = list){
}
You can always create an ArrayList of Objects. But it will not be very useful to you. Suppose you have created the Arraylist like this:
List<Object> myList = new ArrayList<Object>();
and add objects to this list like this:
myList.add(new Integer("5"));
myList.add("object");
myList.add(new Object());
You won't face any problem while adding and retrieving the object but it won't be very useful.
You have to remember at what location each type of object is it in order to use it. In this case after retrieving, all you can do is calling the methods of Object on them.
You can just add objects of diffefent "Types" to an instance of ArrayList. No need create an ArrayList. Have a look at the below example,
You will get below output:
Beginning....
Contents of array: [String, 1]
Size of the list: 2
This is not an Integer String
This is an Integer 1
package com.viswa.examples.programs;
import java.util.ArrayList;
import java.util.Arrays;
public class VarArrayListDemo {
#SuppressWarnings({ "rawtypes", "unchecked" })
public static void main(String[] args) {
System.out.println(" Beginning....");
ArrayList varTypeArray = new ArrayList();
varTypeArray.add("String");
varTypeArray.add(1); //Stored as Integer
System.out.println(" Contents of array: " + varTypeArray + "\n Size of the list: " + varTypeArray.size());
Arrays.stream(varTypeArray.toArray()).forEach(VarArrayListDemo::checkType);
}
private static <T> void checkType(T t) {
if (Integer.class.isInstance(t)) {
System.out.println(" This is an Integer " + t);
} else {
System.out.println(" This is not an Integer" + t);
}
}
}
Just use Entry (as in java.util.Map.Entry) as the list type, and populate it using (java.util.AbstractMap’s) SimpleImmutableEntry:
List<Entry<Integer, String>> sections = new ArrayList<>();
sections.add(new SimpleImmutableEntry<>(anInteger, orString)):
For me this method works perfectly fine in jdk 16
import java.util.ArrayList;
public class Array {
public static void main(String[] args) {
ArrayList arrayList= new ArrayList();
arrayList.add("alien");
arrayList.add(1);
arrayList.add(0,'b');
System.out.println(arrayList);
System.out.println((arrayList.get(0)) instanceof Integer);
}
}
Output
[b, alien, 1]
false
User Defined Class Array List Example
import java.util.*;
public class UserDefinedClassInArrayList {
public static void main(String[] args) {
//Creating user defined class objects
Student s1=new Student(1,"AAA",13);
Student s2=new Student(2,"BBB",14);
Student s3=new Student(3,"CCC",15);
ArrayList<Student> al=new ArrayList<Student>();
al.add(s1);
al.add(s2);
al.add(s3);
Iterator itr=al.iterator();
//traverse elements of ArrayList object
while(itr.hasNext()){
Student st=(Student)itr.next();
System.out.println(st.rollno+" "+st.name+" "+st.age);
}
}
}
class Student{
int rollno;
String name;
int age;
Student(int rollno,String name,int age){
this.rollno=rollno;
this.name=name;
this.age=age;
}
}
Program Output:
1 AAA 13
2 BBB 14
3 CCC 15

Is it possible to check, if a function was called?

I have an ArrayList of objects, which I need to sort using two attributes (using Comparators). I need to save the sorted output to a text file with a different name, depending on the attribute used to sort. For example, if the list is sorted by attribute1 then file will be attribute1.txt, if attribute2 the file will be attribute2.txt.
How I want it to work (pseudocode):
if(sortedByAtr1){
FileWriter fwstream = new FileWriter(sortedByAtribute1.getName()+".txt");
}
else(sortedByAtr2){
FileWriter fwstream = new FileWriter(sortedByAtribute2.getName()+".txt");
}
Is this possible?
I appreciate any advice.
Thanks.
Servo
Here's an object-oriented approach to solving this requirement.
Use a wrapper for the List and its sorting attribute:
public class ListSorter<V> {
private final List<V> values;
private String sortingAttribute;
public ListSorter(List<V> values) {
this.values = values;
}
public void sort(AttributeComparator<V> comparator) {
Collections.sort(values, comparator);
sortingAttribute = comparator.getSortingAttribute();
}
public String getSortingAttribute() {
return sortingAttribute;
}
}
Extend the Comparator interface so you can get your attribute name:
public interface AttributeComparator<T> extends Comparator<T> {
public String getSortingAttribute();
}
Create custom AttributeComparators like this:
public class FooBarComparator implements AttributeComparator<Foo> {
public int compare(Foo foo1, Foo foo2) {
// skipped nullchecks for brevity
return foo1.getBar().compare(foo2.getBar());
}
public String getSortingAttribute() {
return "bar";
}
}
Use:
List<Foo> yourList = new ArrayList<Foo>();
ListSorter<Foo> example = new ListSorter<Foo>(yourList);
AttributeComparator comparator1 = new FooBarComparator();
example.sort(comparator1);
FileWriter fwstream = new FileWriter(example.getSortingAttribute() +".txt");

Write Java Comparator

I have created a Vector object to store data in Table object as Vector<Table>. Vector<Table> contains components as below.
[Vector<Record> records, String tableName, String keyColumnName, int recordCount, int columnCount]
I need to sort tableName in above Vector to my own order and return Vector<Table> with sorted tableNames for other processes.
I have wrote method as below.
private Vector<Table> orderTables(Vector<Table> loadTables) {
List<String> tableNames = new ArrayList<String>();
for (Table table : loadTables) {
String tblName = table.getTableName();
tableNames.add(tblName);
}
Collections.sort(tableNames, new MyComparable());
return null;
}
But I have no idea about how to write Comparator to this. My own sort order is stored in .properties file. I can read it and get value. But I have no idea about how to compare it.
How could I do it?
Before clarification
You need to write a Comparator for Table objects that delegates to the tableName's comparator:
new Comparator<Table>() {
#Override public int compare(Table one, Table two) {
return one.getTableName().compareTo(two.getTableName());
}
}
Note that this will consider Tables that have the same name to be equal. This can mess things up if you put these tables in a HashMap or HashSet. To avoid this, you can detect this case and return one.hashCode() - two.hashCode() if the table names are the same.
Guava's ComparisonChain is a convenient way to write such multi-stage comparisons:
new Comparator<Table>() {
#Override public int compare(Table one, Table two) {
return ComparisonChain.start()
.compare(one.getTableName(), two.getTableName())
.compare(one.hashCode(), two.hashCode())
.result();
}
}
After clarification
Okay, the question is to impose a predefined sorting order rather than sorting the Tables by name. In that case, you need to make a Comparator that is aware of the ordering defined in the .properties file.
One way to achieve this is to initialize a mapping of table names to sorting order indices, and refer that mapping during the comparison. Given the property value:
SORT_ORDER = SALES,SALE_PRODUCTS,EXPENSES,EXPENSES_ITEMS
The mapping should look like:
{
SALES: 0,
SALE_PRODUCTS: 1,
EXPENSES: 2,
EXPENSES_ITEMS: 3
}
Here's what the comparator would look like:
private static class PredefinedOrderComparator implements Comparator<Table> {
public PredefinedOrderComparator() {
// Initialize orderIndex here
}
private final Map<String, Integer> orderIndex;
#Override public int compare(Table one, Table two) {
return orderIndex.get(one.getTableName()) - orderIndex.get(two.getTableName());
}
}
To populate orderIndex from the property value, you need to:
Get the comma-separated list using getProperty() as you mentioned
Split that value on comma (I recommend using Guava's Splitter, but String.split or others will work too)
Initialize a new HashMap<String, Integer> and an int index = 0
Iterate through the split tokens, map the current token to index and increment index
Note the implicit assumption that none of the table names have a comma in it.
public class MyComparable implements Comparator<Table>{
#Override
public int compare(Table table1, Table table2) {
return (table1.getTableName().compareTo(table2.getTableName());
}
}
make sure that you have overridden the hashcode and equals in Table class to achieve this.
I wrote you a very simple example on how to work with a Comparator. If you create a class called Main, copy paste below contents in it, compile and run it, you can see what's going on.
A comparator just needs to implement an interface. For this it needs to implement one method (public int compare(T arg0, T arg1). There you specify how a collection will get sorted; in this case according to the alfabet.
I hope this helps you.
import java.util.*;
public class Main {
public static void main(String[] args) {
System.out.println("Start\n");
List<Item> items = new ArrayList<Item>();
for(String s : new String[]{"mzeaez", "xcxv", "hjkhk", "azasq", "iopiop"}) {
items.add(createItem(s));
}
System.out.println("Items before sort:");
System.out.println(Item.toString(items));
Collections.sort(items, new ItemComparator());
System.out.println("Items after sort:");
System.out.println(Item.toString(items));
System.out.println("End");
}
private static Item createItem(String s) {
Item item = new Item();
item.setS(s);
return item;
}
}
class Item {
private String s;
public String getS() {
return s;
}
public void setS(String s) {
this.s = s;
}
#Override
public String toString() {
return "Item: " + s;
}
public static String toString(Collection<Item> items) {
String s = "";
for(Item item : items) {
s += item + "\n";
}
return s;
}
}
class ItemComparator implements Comparator<Item> {
#Override
public int compare(Item item1, Item item2) {
return item1.getS().compareTo(item2.getS());
}
}

Categories