Пользователь пока ничего не рассказал о себе

Наибольший вклад в теги

Все теги (2)

Лучшие ответы пользователя

Все ответы (2)
  • Как сделать ID для объектов?

    @nubus4000
    Можно использовать такой говнокод. Смысл - создавать класс на лету, если у него нет поля id или его нельзя нормально сравнить по equals и hashcode. Код надо подкрутить, он может не сработать. Писал на лету так сказать.

    import java.lang.reflect.*;
    import java.util.*;
    import java.util.concurrent.atomic.*;
    
    public class SimpleStorage {
    
        private Map<Integer, Object> objects = new HashMap<>();
        private AtomicInteger idGenerator = new AtomicInteger(0);
        private ClassMaker classMaker = new ClassMaker(0, null, null);
    
        private static final String[] EQUALS_NOT_SUPPORTED = {}; //указать имя классов, которые не поддерживают equals и hasCode
    
        public Integer getId(Object obj) {
            Object finalObj = obj;
            boolean isEqualsNotSupported = Arrays.stream(EQUALS_NOT_SUPPORTED)
                    .anyMatch(typeName -> finalObj.getClass().getCanonicalName().equalsIgnoreCase(typeName));
    
            if (isEqualsNotSupported) {
                final Integer id = getIdFromField(obj);
                return objects.entrySet()
                        .stream()
                        .filter(entry -> id.equals(entry.getValue()))
                        .map(Map.Entry::getKey)
                        .findFirst().get();
            }
    
            Object finalObj1 = obj;
            return objects.entrySet()
                    .stream()
                    .filter(entry -> finalObj1.equals(entry.getValue()))
                    .map(Map.Entry::getKey)
                    .findFirst().get();
        }
    
        public void add(Object obj) {
            Integer newId = idGenerator.incrementAndGet();
            obj = classMaker.createClassWithId(newId);
            objects.put(newId, obj);
        }
    
        public Object get(Integer id) {
            return objects.get(id);
        }
    
        private Integer getIdFromField(Object obj) {
            try {
                Field field = obj.getClass().getField(ClassMaker.FIELD_ID);
                field.setAccessible(true);
                return (Integer) field.get(obj);
            } catch (NoSuchFieldException | IllegalAccessException e) {
                return null;
            }
        }
    
    }


    import java.io.*;
    import java.net.*;
    import java.util.*;
    import javax.tools.*;
    
    public class ClassMaker {
    
        public static final String FIELD_ID = "id";
    
        private Integer id = 0;
        private String className;
        private String sourceCode;
        private File sourceFile;
    
        public ClassMaker(Integer id, String className, String sourceCode) {
            this.id = id;
            this.className = className;
            this.sourceCode = sourceCode;
        }
    
        public Object createClassWithId(Integer id) {
            if (id != null)
                this.id = id;
    
            sourceCode = createSimpleString(id);
            Object obj = null;
            try (FileWriter writer = new FileWriter(createTmpFile())) {
                writer.write(sourceCode);
                compileClass();
                className = sourceFile.getName().split("\\.")[0];
                URLClassLoader classLoader = URLClassLoader.newInstance(new URL[]{sourceFile.getParentFile().toURI().toURL()});
                Class<?> newClass = classLoader.loadClass(className);
                obj = newClass.newInstance();
            } catch (IOException e) {
                throw new RuntimeException(e);
            } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
                e.printStackTrace();
            }
            return obj;
        }
    
        private void compileClass() throws IOException {
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
            File parentDirectory = sourceFile.getParentFile();
            fileManager.setLocation(StandardLocation.CLASS_OUTPUT, Collections.singletonList(parentDirectory));
            Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(Collections.singletonList(sourceFile));
            compiler.getTask(null, fileManager, null, null, null, compilationUnits).call();
            fileManager.close();
        }
    
        private File createTmpFile() throws IOException {
            File sourceFile = File.createTempFile(className, ".java");
            sourceFile.deleteOnExit();
            this.sourceFile = sourceFile;
            return sourceFile;
        }
    
        private String createSimpleString(Integer id) {
            StringBuilder classBuilder = new StringBuilder();
            classBuilder.append("public class ")
                    .append(className)
                    .append(" {")
                    .append("private Integer id = ")
                    .append(id)
                    .append(";")
                    .append("    public void setId(Integer id) {\n")
                    .append("        this.id = id;\n").append("    }\n")
                    .append("\n").append("    public Integer getId() {\n")
                    .append("        return id;\n")
                    .append("    }").append("    @Override\n")
                    .append("    public boolean equals(Object o) {\n")
                    .append("        if (this == o) return true;\n")
                    .append("        if (o == null || getClass() != o.getClass()) return false;\n")
                    .append("\n")
                    .append(className)
                    .append(" that = ")
                    .append("(").append(className).append(")").append(" o;")
                    .append("\n")
                    .append("        return id != null ? id.equals(that.id) : that.id == null;\n")
                    .append("    }\n").append("\n").append("    @Override\n")
                    .append("    public int hashCode() {\n")
                    .append("        return id != null ? id.hashCode() : 0;\n")
                    .append("    }\n")
                    .append("}");
            return classBuilder.toString();
        }
    }


    А вообще странная задача - давать всем уникальные id. Откуда объекты берутся? Почему нельзя инкапсулировать всякие сеты и листы внутри пользовательских классов?
    Ответ написан
    Комментировать