private class FileType extends Object {
private String Name;
private String Type;
public FileType() {
Name = null;
Type = null;
}
public void setFileType(String n, String t) {
Name = n;
Type = t;
}
public int compareTo(FileType ft) {
String decodedFileName = null;
String decodedInputName = null;
try {
decodedFileName = URLDecoder.decode(this.Name, "UTF-8");
decodedInputName = URLDecoder.decode(ft.Name, "UTF-8");
}
catch(UnsupportedEncodingException e) {
}
return decodedFileName.compareToIgnoreCase(decodedInputName);
}
}
Above code is my define class for file list.
I had implement compare file name.
The type may Folder or File.
But I want to sort file first priority is Type, and second priority is Name.
How can arrive it?
You have to implement Comparable / compareTo method.
Use Comparator Interface from java.util package to sort in more than one way......
Use the compare(T t1, T t2) method of Comparator
Eg:
Here is an example from site http://www.mkyong.com
import java.util.Comparator;
public class Fruit{
private String fruitName;
private String fruitDesc;
private int quantity;
public Fruit(String fruitName, String fruitDesc, int quantity) {
super();
this.fruitName = fruitName;
this.fruitDesc = fruitDesc;
this.quantity = quantity;
}
public String getFruitName() {
return fruitName;
}
public void setFruitName(String fruitName) {
this.fruitName = fruitName;
}
public String getFruitDesc() {
return fruitDesc;
}
public void setFruitDesc(String fruitDesc) {
this.fruitDesc = fruitDesc;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public static Comparator<Fruit> FruitNameComparator
= new Comparator<Fruit>() {
public int compare(Fruit fruit1, Fruit fruit2) {
String fruitName1 = fruit1.getFruitName().toUpperCase();
String fruitName2 = fruit2.getFruitName().toUpperCase();
//ascending order
return fruitName1.compareTo(fruitName2);
//descending order
//return fruitName2.compareTo(fruitName1);
}
};
}
Compare both types. If the comparison is different from 0, return it as a result. If equal to 0, then compare the names.
Note that:
Extending Object is unnecessary: it's the default
Fields should start with a lower-case letter: name, type na dnot Name, Type
Your class should implement Comparable<FileType>
I would choose another name for the class: It's not a file type, but a file name associated to a file type
I would use an enum rather than a String for file types, since you only have two valid instances of file types
You should never ignore exceptions like you're doing. BTW, if this exception occurs, it could lead to a NullPointerException. Wrap the exception into a runtime exception and throw this runtime exception:
catch(UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
Your compareTo method doesn't handle null names, although the default constructor assigns null to the name. Fix the method or the constructor. It seems to me that a file name should never be null, so I would fix the constructor.
if (this.Type.equals(ft.Type)){
return decodedFileName.compareTo(decodedInputName);
}
else{
return this.Type.compareTo(ft.Type);
}
You first compare the type and then the decoded name.
I cached the decodedFileName value directly in the class to prevent calling URLDecoder.decode too much.
private class FileType extends Object implements Comparable<FileType>{
private String name;
private String decodedFileName;
private String type;
public FileType(String n, String t) {
name = n;
try {
decodedFileName = URLDecoder.decode(this.name, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
type = t;
}
public int compareTo(FileType other) {
int result = type.compareToIgnoreCase(other.type);
if (result == 0){
result = decodedFileName.compareToIgnoreCase(other.decodedFileName);
}
return result;
}
}
if you have only two types, why dont make them enum?
then first you compare type.ordinal, if there are equal then compare names,
and also prevents from putting unwanted values there
Related
Is there some way to print different data from an ArrayList containing different objects?
For example, I created two basic classes:
import java.util.*;
class Furniture{
String name;
int weight;
Furniture(String name, int weight){
this.name = name;
this.weight = weight;
}
String getName(){
return name;
}
int getWeight(){
return weight;
}
}
}
class Resident{
String name;
Resident(String name){
this.name = name;
}
String getName(){
return name;
}
}
Then I stored them in an ArrayList<Object> and wanted to print the names, by using declared below printArrayList method:
public class Main{
public static <E> void printArrayList(ArrayList<E> arrayToPrint){
for(E element : arrayToPrint){
try{
System.out.println(element.getName());
}
catch(Exception e){
System.out.println("Exception e: " + e);
}
}
}
public static void main(String []args){
Furniture sofa = new Furniture("Sofa", 5);
Resident mike = new Resident("Mike");
ArrayList<Object> arrayList = new ArrayList<>();
arrayList.add(sofa);
arrayList.add(mike);
printArrayList(arrayList);
}
Now, I know that not all objects can have a variable name or declared get method, therefore I tried to exclude these cases by try/catch.
I also tried to exclude it by using fe:
if(elements.getName() == null)
Still, same results.
You don't need to use a parameterized type. Rather introduce a specific interface (for example NameAware) that exposes the getName() method that your classes with implement. In this way you could rely on a common type.
public interface NameAware{
String getName();
}
public class Resident implements NameAware{
...
public String getName(){
return name;
}
}
public class Furniture implements NameAware{
...
public String getName(){
return name;
}
}
And define your method as :
public static void printArrayList(ArrayList<NameAware> arrayToPrint) {
for (NameAware element : arrayToPrint) {
try {
System.out.println(element.getName());
} catch (Exception e) {
System.out.println("Exception e: " + e);
}
}
}
Note that you should change your actual code from :
ArrayList<Object> arrayList = new ArrayList<>();
to
ArrayList<NameAware> arrayList = new ArrayList<>();
The best practice would be to declare an interface with the getName method, and have both Furniture and Resident implement it.
public interface Namable {
public String getName();
}
Then, use a List<Namable> instead of a List<Object>:
Furniture sofa = new Furniture("Sofa", 5);
Resident mike = new Resident("Mike");
List<Namable> arrayList = new ArrayList<>();
arrayList.add(sofa);
arrayList.add(mike);
for (Namable n : arrayList) {
System.out.println(n.getName());
}
I created a parceable class and wanted to use it for data transfer from fragment A to B. I did it like in many other tutorials but I can't instantiate from parceable object class. it always says, that I have to put in 'Parcel in' as parameter.
Here my object class:
public class DataObject implements Parcelable {
private int number1 = 0;
private int number2 = 0;
private String name = "";
public int getNumber1() {
return number1;
}
public void setNumber1(int number1) {
this.number1 = number1;
}
public int getNumber2() {
return number2;
}
public void setNumber2(int number2) {
this.number2 = number2;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
protected DataObject(Parcel in) {
number1 = in.readInt();
number2 = in.readInt();
name = in.readString();
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(number1);
dest.writeInt(number2);
dest.writeString(name);
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<DataObject> CREATOR = new Parcelable.Creator<DataObject>() {
#Override
public DataObject createFromParcel(Parcel in) {
return new DataObject(in);
}
#Override
public DataObject[] newArray(int size) {
return new DataObject[size];
}
};
}
And here is how I use objects from this type:
DataObject bla = new DataObject();
bla.setNumber1(1);
bla.setNumber2(2);
bla.setName("TestName");
When I hover the red highlighted constructor it says:
DataObject (Parcel) in DataObject cannot be applied
and compiler says:
Error:(30, 50) error: constructor PointCardMainData in class
PointCardMainData cannot be applied to given types;
required: Parcel
found: no arguments
reason: actual and formal argument lists differ in length
Has anybody an idea what is missing? Do I have to set something in the manifest- oder gradle-file? do I have to do something before building the project?
best regards
You've written just one constructor in the DataObject class, and it specifies how to make a DataObject from a Parcel. Now you're trying to make a DataObject without a parcel. You need to either add a Parcel to the line DataObject bla = new DataObject(); or add a new constructor.
So you might write
Parcel theParcel = new Parcel();
DataObject bla = new DataObject(theParcel);
Or you might have a constructor in your DataObject class like
public DataObject(){
}
Add a constructor in your DataObject class
public DataObject()
{}
I have to overwrite the equals for my train class which has three attributes : number, wagons and type; Two trains are equal only if their numbers are the same. I have to test whether are duplicates in my train SET. How can I do that ?
This is what i've done so far :
public class Train {
private int number;
private String type;
private int wagons;
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public int getWagons() {
return wagons;
}
public void setWagons(int wagons) {
this.wagons = wagons;
}
#Override
public boolean equals(Object obj) {
Train otherTrain = (Train) obj;
boolean equal = false;
if (otherTrain.getNumber() == this.getNumber()) {
equal = true;
}
return equal;
}
Trains DAO :
public class TrainsDAO {
private Set<Train> trainSet = new HashSet<Train>();
public Set<Train> pupulateTheSet() {
Random random = new Random();
for (int i = 1; i < 1000; i++) {
Train train = new Train();
train.setNumber(random.nextInt(10));
train.setWagons(random.nextInt(30));
train.setType("Inter-city");
trainSet.add(train);
}
return trainSet;
}
public static void main(String[] args) {
TrainsDAO trainsDAO = new TrainsDAO();
Set<Train> trains = trainsDAO.pupulateTheSet();
for (Train train : trains) {
System.out.println(train);
}
}
}
And the tests:
public class TrainTest extends TestCase {
private TrainsDAO trainsDAO = new TrainsDAO();
private Set<Train> trainSet = trainsDAO.pupulateTheSet();
public TrainTest(String name) {
super(name);
}
#Override
protected void setUp() throws Exception {
super.setUp();
}
#Test
public void testIfThereAreEqualValuesInSet() {
assertTrue(!duplicateFound());
}
private boolean duplicateFound() {
//check if there are duplicates in the set return true if there are no false otherwise
return false;
}
}
Your equals override as implemented right now may throw:
NullPointerException if the argument is null
ClassCastException as there's no instanceof check before casting the Object argument to Train
You may want to fix that.
More importantly for hash-based collections, you need to #Override the Object#hashCode method consistently with equals (that is, by returning a hash code based on your train number).
Overriding hashCode correctly will ensure your Trains will be put in different hash buckets if their numbers are different.
Also note: it seems pointless to have unit tests checking for duplicate values in a Set - the whole point of a Set is that it does not allow duplicates.
Docs here.
How I can access the Name field?
public class Animals {
public enum animal{
a1("CAT", 4),
a2("DOG", 4);
}
String Name;
int E;
public animal(String Name, int E){
this.Name = Name;
this.E = E;
}
}
This can be done, but you have a number of syntax errors. The key is to provide getter methods for the enum member variables.
public enum Animal {
a1("CAT", 4), a2("DOG", 4);
private String Name;
private int E;
private animal(String Name, int E)
{
this.Name = Name;
this.E = E;
}
public String getName() {
return Name;
}
public int getE() {
return E;
}
}
You could then access these values anywhere in the rest of your program.
Animal.a1.getName();
Assuming you have an inner enum like this:
public class Animals {
public enum Animal {
a1("CAT", 4), a2("DOG", 4);
final String Name;
final int E;
private Animal(String Name, int E) {
this.Name = Name;
this.E = E;
}
public String getName() {
return Name;
}
}
}
You can get the name using (field so no parenthesis)
Animals.Animal.a1.Name
but better to make all fields private and use the getter:
Animals.Animal.a1.getName()
If I understand correctly, I believe the OP is asking:
“Given a string, "a1", return an object of type Animal with the value Animal.a1”
… in which case, the method you're looking for would be Enum.valueOf(Class,String)
String enumName = "a1";
Animal a = Enum.valueOf (Animal.class (enumName));
if (null == a) {
// error handler …
} else {
// do something interesting with “a”
}
How can I get the name of a Java Enum type given its value?
I have the following code which works for a particular Enum type, can I make it more generic?
public enum Category {
APPLE("3"),
ORANGE("1"),
private final String identifier;
private Category(String identifier) {
this.identifier = identifier;
}
public String toString() {
return identifier;
}
public static String getEnumNameForValue(Object value){
Category[] values = Category.values();
String enumValue = null;
for(Category eachValue : values) {
enumValue = eachValue.toString();
if (enumValue.equalsIgnoreCase(value)) {
return eachValue.name();
}
}
return enumValue;
}
}
You should replace your getEnumNameForValue by a call to the name() method.
Try below code
public enum SalaryHeadMasterEnum {
BASIC_PAY("basic pay"),
MEDICAL_ALLOWANCE("Medical Allowance");
private String name;
private SalaryHeadMasterEnum(String stringVal) {
name=stringVal;
}
public String toString(){
return name;
}
public static String getEnumByString(String code){
for(SalaryHeadMasterEnum e : SalaryHeadMasterEnum.values()){
if(e.name.equals(code)) return e.name();
}
return null;
}
}
Now you can use below code to retrieve the Enum by Value
SalaryHeadMasterEnum.getEnumByString("Basic Pay")
Use Below code to get ENUM as String
SalaryHeadMasterEnum.BASIC_PAY.name()
Use below code to get string Value for enum
SalaryHeadMasterEnum.BASIC_PAY.toString()
Try, the following code..
#Override
public String toString() {
return this.name();
}
Here is the below code, it will return the Enum name from Enum value.
public enum Test {
PLUS("Plus One"), MINUS("MinusTwo"), TIMES("MultiplyByFour"), DIVIDE(
"DivideByZero");
private String operationName;
private Test(final String operationName) {
setOperationName(operationName);
}
public String getOperationName() {
return operationName;
}
public void setOperationName(final String operationName) {
this.operationName = operationName;
}
public static Test getOperationName(final String operationName) {
for (Test oprname : Test.values()) {
if (operationName.equals(oprname.toString())) {
return oprname;
}
}
return null;
}
#Override
public String toString() {
return operationName;
}
}
public class Main {
public static void main(String[] args) {
Test test = Test.getOperationName("Plus One");
switch (test) {
case PLUS:
System.out.println("Plus.....");
break;
case MINUS:
System.out.println("Minus.....");
break;
default:
System.out.println("Nothing..");
break;
}
}
}
In such cases, you can convert the values of enum to a List and stream through it.
Something like below examples. I would recommend using filter().
Using ForEach:
List<Category> category = Arrays.asList(Category.values());
category.stream().forEach(eachCategory -> {
if(eachCategory.toString().equals("3")){
String name = eachCategory.name();
}
});
Or, using Filter:
When you want to find with code:
List<Category> categoryList = Arrays.asList(Category.values());
Category category = categoryList.stream().filter(eachCategory -> eachCategory.toString().equals("3")).findAny().orElse(null);
System.out.println(category.toString() + " " + category.name());
When you want to find with name:
List<Category> categoryList = Arrays.asList(Category.values());
Category category = categoryList.stream().filter(eachCategory -> eachCategory.name().equals("Apple")).findAny().orElse(null);
System.out.println(category.toString() + " " + category.name());
Hope it helps! I know this is a very old post, but someone can get help.
I believe it's better to provide the required method in the enum itself. This is how I fetch Enum Name for a given value. This works for CONSTANT("value") type of enums.
public enum WalletType {
UPI("upi-paymode"),
PAYTM("paytm-paymode"),
GPAY("google-pay");
private String walletType;
WalletType(String walletType) {
this.walletType = walletType;
}
public String getWalletType() {
return walletTypeValue;
}
public WalletType getByValue(String value) {
return Arrays.stream(WalletType.values()).filter(wallet -> wallet.getWalletType().equalsIgnoreCase(value)).findFirst().get();
}
}
e.g. WalletType.getByValue("google-pay").name()
this will give you - GPAY
enum MyEnum {
ENUM_A("A"),
ENUM_B("B");
private String name;
private static final Map<String,MyEnum> unmodifiableMap;
MyEnum (String name) {
this.name = name;
}
public String getName() {
return this.name;
}
static {
Map<String,MyEnum> map = new ConcurrentHashMap<String, MyEnum>();
for (MyEnum instance : MyEnum.values()) {
map.put(instance.getName().toLowerCase(),instance);
}
unmodifiableMap = Collections.unmodifiableMap(map);
}
public static MyEnum get (String name) {
return unmodifiableMap.get(name.toLowerCase());
}
}
Now you can use below code to retrieve the Enum by Value
MyEnum.get("A");